package cc.rengu.igas.momp.core.service.trans;

import cc.rengu.igas.momp.common.constant.CommonConstant;
import cc.rengu.igas.momp.common.dao.*;
import cc.rengu.igas.momp.common.dao.impl.*;
import cc.rengu.igas.momp.common.entity.*;
import cc.rengu.igas.momp.common.enums.*;
import cc.rengu.igas.momp.common.util.MompDateUtil;
import cc.rengu.igas.momp.facade.bean.PaymentReturnOrderMchntFeeDiscountInfoBean;
import cc.rengu.igas.momp.facade.request.ComboMchntFeeDiscountRefundRequest;
import cc.rengu.igas.momp.facade.response.ComboMchntFeeDiscountRefundResponse;
import cc.rengu.jradp.mods.dbs.Database;
import cc.rengu.oltp.service.base.RadpService;
import cc.rengu.oltp.service.common.constant.AppConfigConstant;
import cc.rengu.oltp.service.common.constant.AppParamConstant;
import cc.rengu.oltp.service.common.constant.TreeNodeConstant;
import cc.rengu.oltp.service.common.enums.ChannelEnum;
import cc.rengu.oltp.service.common.enums.OltpRpcdEnum;
import cc.rengu.oltp.service.common.enums.TransStatusEnum;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.service.model.BizResponse;
import cc.rengu.oltp.utility.util.*;
import cc.rengu.utility.base.StringUtil;
import com.alibaba.fastjson.JSONObject;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author liujinan
 * @version 1.0.0
 * @date 2020/5/13
 * @description 手续费优惠回退
 */
public class ComboMchntFeeDiscountRefundService extends RadpService {

    /**
     * 交易时间戳
     */
    private String globalTimeStamp;
    /**
     * 交易日期
     */
    private String globalTxnDate;
    private String globalInstId;
    private String globalTraceNo;
    /**
     * 订单明细表 存储本次交易需要插入订单明细表的数据
     */
    private List<TMTxnOrderDet> globalTMTxnOrderDetList;

    /**
     * 是否是最后一笔退货，本次退货完成后原订单为全额退款
     */
    private Boolean isLastDeal = false;
    private BigDecimal zero = BigDecimal.ZERO;
    /**
     * 银行机构代码
     */
    private static final String INST_ID_YT = "816";
    /**
     * 银行 营销活动周期限额2万
     */
    private static final String YT_PERIOD_LIMIT = "20000.00";

    @Override
    protected int bizInit(String s) {
        return CommonConstant.PROCESS_SUCCESS;
    }

    @Override
    protected int bizProcess(String s, int i) {

        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        try {
            ComboMchntFeeDiscountRefundRequest comboMchntFeeDiscountRefundRequest = new ComboMchntFeeDiscountRefundRequest();
            ConvertUtil.convertOutput(comboMchntFeeDiscountRefundRequest);

            ComboMchntFeeDiscountRefundResponse comboMchntFeeDiscountRefundResponse = new ComboMchntFeeDiscountRefundResponse();
            comboMchntFeeDiscountRefundResponse.setHeader(comboMchntFeeDiscountRefundRequest.getHeader());
            BizResponse<ComboMchntFeeDiscountRefundResponse> bizResponse = new BizResponse<>();
            bizResponse.setResult(comboMchntFeeDiscountRefundResponse);

            globalTimeStamp = new SimpleDateFormat(CommonConstant.TIMESTAMP_FORMAT).format(new Date());
            globalTxnDate = comboMchntFeeDiscountRefundRequest.getHeader().getTransDate();
            globalTraceNo = comboMchntFeeDiscountRefundRequest.getHeader().getTraceNo();

            //接口请求报文检查
            checkRequestMessage(comboMchntFeeDiscountRefundRequest);
            // 检查上传字段 不能为负数
            checkOrderDetFieldHasNegativeNumber(comboMchntFeeDiscountRefundRequest);

            // 调用处理流程
            BizResponse<ComboMchntFeeDiscountRefundResponse> bizResponseNew = comboMchntFeeDiscountRefund(xmlTreeUtil, comboMchntFeeDiscountRefundRequest, comboMchntFeeDiscountRefundResponse);

            ConvertUtil.convertInput(bizResponseNew.getResult());
        } catch (BizException e) {
            try {
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.RESP_CODE, e.getCode());
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.RESP_DESC, e.getMessage());
                xmlTreeUtil.setXmlTreeStringValue(CommonConstant.KEY_RESPDESC, e.getMessage());
            } catch (Exception e1) {
                rglog.error(StringUtil.ExceptionToString(e1));
            }
        } catch (Exception e) {
            rglog.error(StringUtil.ExceptionToString(e));
            try {
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.RESP_CODE, OltpRpcdEnum.OLTP_PROCESS_ERROR.getRespCode());
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.RESP_DESC, OltpRpcdEnum.OLTP_PROCESS_ERROR.getRespDesc());
                xmlTreeUtil.setXmlTreeStringValue(CommonConstant.KEY_RESPDESC, e.getMessage());
            } catch (Exception e1) {
                rglog.error(StringUtil.ExceptionToString(e));
            }
        }
        return CommonConstant.PROCESS_SUCCESS;
    }

    @Override
    protected int bizTerminate(String s) {
        return CommonConstant.PROCESS_SUCCESS;
    }

    /**
     * 手续费优惠回退
     *
     * @param comboMchntFeeDiscountRefundRequest
     * @param comboMchntFeeDiscountRefundResponse
     * @param xmlTreeUtil                         内部XML树
     * @throws Exception 异常信息
     * @author liujinan
     * @date 2020/6/11
     */
    private BizResponse<ComboMchntFeeDiscountRefundResponse> comboMchntFeeDiscountRefund(XmlTreeUtil xmlTreeUtil, ComboMchntFeeDiscountRefundRequest comboMchntFeeDiscountRefundRequest, ComboMchntFeeDiscountRefundResponse comboMchntFeeDiscountRefundResponse)
            throws Exception {
        BizResponse<ComboMchntFeeDiscountRefundResponse> bizResponse = new BizResponse<>();
        rglog.info("交易类型 TXN_NUM = {}", comboMchntFeeDiscountRefundRequest.getHeader().getTxnNum());
        //试算交易流水号
        String origTrailTraceNo = comboMchntFeeDiscountRefundRequest.getOrigTrialTraceNo();
        //试算交易日期
        String origTrailTxnDate = comboMchntFeeDiscountRefundRequest.getOrigTrialTxnDate();

        List<PaymentReturnOrderMchntFeeDiscountInfoBean> feeReturnOrderList;
        //如果试算交易流水号和日期不为空，则说明已经经过试算了
        if (null != origTrailTraceNo && null != origTrailTxnDate) {
            //已试算订单回退
            rglog.info("试算交易流水号<{}>,试算交易日期为<{}>,进行已试算订单回退！", origTrailTraceNo, origTrailTxnDate);
            feeReturnOrderList = alreadyTrailOrderRefund(xmlTreeUtil, comboMchntFeeDiscountRefundRequest);
        } else {
            //未试算订单回退
            rglog.info("无上送试算交易日期，进行未试算订单回退");
            feeReturnOrderList = noTrailOrderRefund(xmlTreeUtil, comboMchntFeeDiscountRefundRequest, comboMchntFeeDiscountRefundResponse);
        }

        bizResponse.setRspSysId(ChannelEnum.MOMP.getChannelType());
        bizResponse.setRespCode(RespCodeEnum.TRANS_SUCCESS.getRespCode());
        bizResponse.setRespDesc(RespCodeEnum.TRANS_SUCCESS.getRespDesc());

        comboMchntFeeDiscountRefundResponse.setRespCode(RespCodeEnum.TRANS_SUCCESS.getRespCode());
        comboMchntFeeDiscountRefundResponse.setRespDesc(RespCodeEnum.TRANS_SUCCESS.getRespDesc());
        comboMchntFeeDiscountRefundResponse.setFeeReturnOrderList(feeReturnOrderList);
        bizResponse.setResult(comboMchntFeeDiscountRefundResponse);

        return bizResponse;
    }

    /**
     * 已试算订单回退
     *
     * @return int
     * @throws Exception 异常信息
     * @author liujinan
     * @date 2020/6/4
     */
    private List<PaymentReturnOrderMchntFeeDiscountInfoBean> alreadyTrailOrderRefund(XmlTreeUtil xmlTreeUtil, ComboMchntFeeDiscountRefundRequest comboMchntFeeDiscountRefundRequest) throws Exception {

        String instId = comboMchntFeeDiscountRefundRequest.getHeader().getInstId();
        String transDate = comboMchntFeeDiscountRefundRequest.getHeader().getTransDate();
        //原交易流水号
        String origTraceNo = comboMchntFeeDiscountRefundRequest.getOrigTraceNo();
        //原交易日期
        String origTraceDate = comboMchntFeeDiscountRefundRequest.getOrigTxnDate();
        //试算交易流水号
        String origTrailTraceNo = comboMchntFeeDiscountRefundRequest.getOrigTrialTraceNo();
        //试算交易日期
        String origTrailTxnDate = comboMchntFeeDiscountRefundRequest.getOrigTrialTxnDate();

        //查询原手续费优惠回退试算订单流水
        rglog.info("机构<{}>在<{}>的原试算交易订单<{}>流水信息查询开始...", instId, origTrailTxnDate, origTrailTraceNo);
        TMTxnOrderMapper tmTxnOrderMapper = new TMTxnOrderMapperImpl();
        TMTxnOrder oriTMTxnOrderTrial = tmTxnOrderMapper.selectFeeDiscountOriginalTransactionOrderInfo(instId, origTrailTxnDate, origTrailTraceNo);
        if (null == oriTMTxnOrderTrial) {
            rglog.error("机构<{}>在<{}>的原试算交易订单<{}>流水信息查询失败，未查询到记录！", instId, origTrailTxnDate, origTrailTraceNo);
            throw new BizException(RespCodeEnum.FAILED_TO_CHECK_ORIGINALTRIAL_TXN_INFO_ERROR.getRespCode(), RespCodeEnum.FAILED_TO_CHECK_ORIGINALTRIAL_TXN_INFO_ERROR.getRespDesc());
        }

        //查询原手续费优惠回退试算订单明细信息
        rglog.info("机构<{}>在<{}>的原试算交易订单<{}>明细信息查询开始...", instId, origTrailTxnDate, origTrailTraceNo);
        TMTxnOrderDetMapper tmTxnOrderDetMapper = new TMTxnOrderDetMapperImpl();
        List<TMTxnOrderDet> oriTMTxnOrderDetListTrial = tmTxnOrderDetMapper.selectOriginalTransactionOrderDetailListInfo(instId, origTrailTxnDate, origTrailTraceNo);
        if (null == oriTMTxnOrderDetListTrial || oriTMTxnOrderDetListTrial.isEmpty()) {
            rglog.error("机构<{}>在<{}>的原试算交易订单明细信息<{}>查询失败，未查询到记录！", instId, origTrailTxnDate, origTrailTraceNo);
            throw new BizException(RespCodeEnum.FAILED_TO_CHECK_ORIGINALTRIAL_TXN_INFO_ERROR.getRespCode(), RespCodeEnum.FAILED_TO_CHECK_ORIGINALTRIAL_TXN_INFO_ERROR.getRespDesc());
        }

        //查询原手续费优惠回退试算对应的手续费优惠订单流水
        rglog.info("查询机构<{}>在<{}>的原手续费优惠订单<{}>流水信息开始...", instId, transDate, origTraceNo);
        TMTxnOrder oriTMTxnOrder = tmTxnOrderMapper.selectFeeDiscountOriginalTransactionOrderInfo(instId, origTraceDate, origTraceNo);
        if (null == oriTMTxnOrder) {
            rglog.error("查询机构<{}>在<{}>的原手续费优惠订单流水信息<{}>失败!", instId, transDate, origTraceNo);
            throw new BizException(RespCodeEnum.GET_ORI_TRACE_FAILED.getRespCode(), RespCodeEnum.GET_ORI_TRACE_FAILED.getRespDesc());
        }
        //查询原手续费优惠回退试算对应的手续费优惠订单明细信息
        rglog.info("查询机构<{}>在<{}>的原手续费优惠订单<{}>明细信息开始...", instId, transDate, origTraceNo);
        List<TMTxnOrderDet> tmTxnOrderDetList = tmTxnOrderDetMapper.selectOriginalTransactionOrderDetailListInfo(instId, origTraceDate, origTraceNo);
        if (null == tmTxnOrderDetList || tmTxnOrderDetList.isEmpty()) {
            rglog.error("机构<{}>在<{}>的原交易订单明细信息<{}>查询失败!", instId, origTraceDate, origTraceNo);
            throw new BizException(RespCodeEnum.FAILED_TO_CHECK_ORIGINAL_TXNDET_INFO_ERROR.getRespCode(), RespCodeEnum.FAILED_TO_CHECK_ORIGINAL_TXNDET_INFO_ERROR.getRespDesc());
        }

        /* 开启数据库事务 */
        String dbPoolName = XmlConfigUtil.getXmlConfigCacheKeyValue(AppConfigConstant.DATABASE_CONF_NODE, AppConfigConstant.MOMP_POOL_NAME);
        String corporation = xmlTreeUtil.getXmlTreeStringValue(AppParamConstant.CORPORATION);
        if (null != corporation && !corporation.isEmpty()) {
            String dbPoolCashNode = corporation.trim() + AppParamConstant.DATABASE_CONF_NODE;
            dbPoolName = XmlConfigUtil.getXmlConfigCacheKeyValue(dbPoolCashNode, AppConfigConstant.MOMP_POOL_NAME);
        }
        DbsUtil dbsUtil = new DbsUtil(dbPoolName);
        dbsUtil.dbsBeginTransaction();

        List<PaymentReturnOrderMchntFeeDiscountInfoBean> feeReturnOrderList = new ArrayList<>();
        try {
            //循环遍历原手续费优惠回退试算订单明细
            for (TMTxnOrderDet oriTMTxnOrderDetTrial : oriTMTxnOrderDetListTrial) {
                String mchntNo = oriTMTxnOrderDetTrial.getMchntNo();
                //关联信息
                String relativeDataTrail = oriTMTxnOrderDetTrial.getRelativeData();
                JSONObject relativeDataJsonTrail = JSONObject.parseObject(relativeDataTrail);
                //商户应收手续费金额
                String mchntFeeReceivable = relativeDataJsonTrail.get("mchntFeeReceivable").toString();
                //商户手续费优惠营销活动编号
                String mchntFeeDiscountMcNo = oriTMTxnOrderDetTrial.getMcNo();
                //手续费优惠金额
                String mchntFeeDiscount = oriTMTxnOrderDetTrial.getSubsidy();
                //实收手续费金额
                String mchntFeeActual = new BigDecimal(oriTMTxnOrderDetTrial.getOriginalAmt()).subtract(new BigDecimal(oriTMTxnOrderDetTrial.getSubsidy())).toString();
                //回退试算订单金额
                String orderAmt = relativeDataJsonTrail.get("orderAmt").toString();

                PaymentReturnOrderMchntFeeDiscountInfoBean paymentReturnOrderMchntFeeDiscountInfoBean = new PaymentReturnOrderMchntFeeDiscountInfoBean();
                paymentReturnOrderMchntFeeDiscountInfoBean.setMchntNo(mchntNo);
                paymentReturnOrderMchntFeeDiscountInfoBean.setOrderAmt(orderAmt);
                paymentReturnOrderMchntFeeDiscountInfoBean.setMchntFeeReceivable(mchntFeeReceivable);
                paymentReturnOrderMchntFeeDiscountInfoBean.setMchntFeeDiscountMcNo(mchntFeeDiscountMcNo);
                paymentReturnOrderMchntFeeDiscountInfoBean.setMchntFeeDiscount(mchntFeeDiscount);
                paymentReturnOrderMchntFeeDiscountInfoBean.setMchntFeeActual(mchntFeeActual);
                feeReturnOrderList.add(paymentReturnOrderMchntFeeDiscountInfoBean);

                //查询退货统计表,并登记或更新退货统计表，同时更新手续费优惠回退试算订单明细和手续费优惠订单明细
                TMStatRefundMapper tmStatRefundMapper = new TMStatRefundMapperImpl();
                TMStatRefund tmStatRefund = tmStatRefundMapper.selectSingleRecordFromTMStatRefund(instId, origTraceDate, origTraceNo, mchntNo);
                if (null == tmStatRefund) {
                    rglog.info("商户号<{}> 原流水号<{}>未取到退货记录，说明之前未有过退货订单,本次插入一条记录!", mchntNo, origTraceNo);
                    //登记退货统计表，更新手续费回退试算订单流水，更新手续费回退试算订单流水明细,判断当前交易是否在原交易日期的统计周期内，如果在需要更新当前交易的单日统计表
                    recordTMStatRefund(oriTMTxnOrder, oriTMTxnOrderTrial, oriTMTxnOrderDetTrial);
                } else {
                    rglog.info("商户号<{}> 原流水号<{}>已取到退货记录，说明之前有过退货订单，本次更新记录", mchntNo, origTraceNo);
                    //更新手续费回退试算订单流水明细,更新手续费优惠订单流水明细,判断当前交易是否在原交易日期的统计周期内，如果在需要更新当前交易的单日统计表
                    updateTMStatRefund(oriTMTxnOrder, oriTMTxnOrderTrial, oriTMTxnOrderDetTrial, tmStatRefund);
                }

                //如果手续费回退的交易有手续费优惠值，则登记订单明细表，如果没有则不登记(当有优惠交易金额没有手续费优惠额时也登记)
                recordRefundTxnOrderDetail(paymentReturnOrderMchntFeeDiscountInfoBean, oriTMTxnOrderDetTrial);
            }
            //更新手续费优惠回退试算订单流水和手续费续费优惠订单流水
            updateTMTxnOrder(oriTMTxnOrder, oriTMTxnOrderTrial);

            //登记本次退款订单流水
            rglog.info("登记交易订单流水<{}>开始...", globalTraceNo);
            recordTxnOrder(comboMchntFeeDiscountRefundRequest, oriTMTxnOrder, feeReturnOrderList);

        } catch (Exception e) {
            rglog.error("手续费优惠回退失败!所有数据库操作回滚!!!");
            //出现异常，回滚数据库数据
            dbsUtil.dbsEndTransaction(false);
            throw new Exception(e);
        }
        dbsUtil.dbsEndTransaction(true);

        return feeReturnOrderList;
    }

    /**
     * 未经试算直接回退的使用处理流程
     *
     * @throws Exception 异常信息
     * @author liujinan
     * @date 2020/6/4
     */
    private List<PaymentReturnOrderMchntFeeDiscountInfoBean> noTrailOrderRefund(XmlTreeUtil xmlTreeUtil, ComboMchntFeeDiscountRefundRequest comboMchntFeeDiscountRefundRequest, ComboMchntFeeDiscountRefundResponse comboMchntFeeDiscountRefundResponse) throws Exception {

        String instId = comboMchntFeeDiscountRefundRequest.getHeader().getInstId();
        String origTxnDate = comboMchntFeeDiscountRefundRequest.getOrigTxnDate();
        String origTraceNo = comboMchntFeeDiscountRefundRequest.getOrigTraceNo();

        //查询原交易订单流水信息
        rglog.info("查询机构<{}>在<{}>的原手续费优惠订单<{}>流水信息开始...", instId, origTxnDate, origTraceNo);
        TMTxnOrderMapper tmTxnOrderMapper = new TMTxnOrderMapperImpl();
        TMTxnOrder tmTxnOrderOrig = tmTxnOrderMapper.selectFeeDiscountOriginalTransactionOrderInfo(instId, origTxnDate, origTraceNo);
        if (null == tmTxnOrderOrig) {
            rglog.error("机构<{}>在<{}>的原交易订单流水信息<{}>查询失败，未查询到记录！", instId, origTxnDate, origTraceNo);
            throw new BizException(RespCodeEnum.GET_ORI_TRACE_FAILED.getRespCode(), RespCodeEnum.GET_ORI_TRACE_FAILED.getRespDesc());
        }

        //查询原交易订单明细信息
        rglog.info("查询机构<{}>在<{}>的原手续费优惠订单<{}>明细信息开始...", instId, origTxnDate, origTraceNo);
        TMTxnOrderDetMapper tmTxnOrderDetMapper = new TMTxnOrderDetMapperImpl();
        List<TMTxnOrderDet> tmTxnOrderDetListOrig = tmTxnOrderDetMapper.selectOriginalTransactionOrderDetailListInfo(instId, origTxnDate, origTraceNo);
        if (null == tmTxnOrderDetListOrig || tmTxnOrderDetListOrig.isEmpty()) {
            rglog.error("机构<{}>在<{}>的原交易订单明细信息<{}>查询失败，未查询到明细记录!", instId, origTxnDate, origTraceNo);
            throw new BizException(RespCodeEnum.FAILED_TO_CHECK_ORIGINAL_TXNDET_INFO_ERROR.getRespCode(), RespCodeEnum.FAILED_TO_CHECK_ORIGINAL_TXNDET_INFO_ERROR.getRespDesc());
        }

        /* 开启数据库事务 */
        String dbPoolName = XmlConfigUtil.getXmlConfigCacheKeyValue(AppConfigConstant.DATABASE_CONF_NODE, AppConfigConstant.MOMP_POOL_NAME);
        String corporation = xmlTreeUtil.getXmlTreeStringValue(AppParamConstant.CORPORATION);
        if (null != corporation && !corporation.isEmpty()) {
            String dbPoolCashNode = corporation.trim() + AppParamConstant.DATABASE_CONF_NODE;
            dbPoolName = XmlConfigUtil.getXmlConfigCacheKeyValue(dbPoolCashNode, AppConfigConstant.MOMP_POOL_NAME);
        }
        DbsUtil dbsUtil = new DbsUtil(dbPoolName);
        dbsUtil.dbsBeginTransaction();

        try {
            //处理商户手续费优惠回退—未经试算直接回退的使用
            processMchntFeeDiscountRefundTrialProcedure(comboMchntFeeDiscountRefundRequest, tmTxnOrderOrig, tmTxnOrderDetListOrig, comboMchntFeeDiscountRefundResponse);

        } catch (Exception e) {
            rglog.error("商户手续费优惠回退试算失败!所有数据库操作回滚!");
            /* 事务处理失败关闭数据库事务 */
            dbsUtil.dbsEndTransaction(false);
            throw new BizException(RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespCode(), RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespDesc());
        }

        /* 事务处理成功关闭数据库事务 */
        dbsUtil.dbsEndTransaction(true);

        return comboMchntFeeDiscountRefundResponse.getFeeReturnOrderList();
    }


    /**
     * 更新订单流水表业务状态
     *
     * @param tmTxnOrder
     * @return int
     * @throws Exception 异常信息
     * @author liujinan
     * @date 2020/5/13
     */
    private int updateTxnOrderBizStatusInfo(TMTxnOrder tmTxnOrder) throws Exception {

        TMTxnOrderMapper tmTxnOrderMapper = new TMTxnOrderMapperImpl();
        int returnCode = tmTxnOrderMapper.updateFeeDiscountOriginalTransactionOrderBizStatus(tmTxnOrder, tmTxnOrder.getBizStatus());
        if (CommonConstant.PROCESS_SUCCESS != returnCode) {
            rglog.error("商户号<{}> 交易流水号<{}> 更新订单流水表业务状态失败!", tmTxnOrder.getMchntNo(), tmTxnOrder.getFrontSeqNum());
            return CommonConstant.PROCESS_FAILED;
        } else {
            return CommonConstant.PROCESS_SUCCESS;
        }
    }


    /**
     * 登记退货统计表，更新手续费回退试算订单流水，更新手续费回退试算订单流水明细
     *
     * @return void
     * @throws Exception 异常信息
     * @author liujinan
     * @date 2020/5/13
     */
    private void recordTMStatRefund(TMTxnOrder oriTMTxnOrder, TMTxnOrder oriTMTxnOrderTrial, TMTxnOrderDet oriTMTxnOrderDetTrial) throws Exception {
        String newTimeStamp = new SimpleDateFormat(CommonConstant.TIMESTAMP_FORMAT).format(new Date());

        TMStatRefund tmStatRefund = new TMStatRefund();
        //机构编码
        tmStatRefund.setInstId(oriTMTxnOrderTrial.getInstId());
        //交易日期
        tmStatRefund.setTxnDate(oriTMTxnOrder.getTxnDate());
        //交易时间
        tmStatRefund.setTxnTime(oriTMTxnOrder.getTxnTime());
        //系统流水号
        tmStatRefund.setSysSeqNum(oriTMTxnOrder.getFrontSeqNum());
        //订单号
        tmStatRefund.setOrderId(oriTMTxnOrder.getOrderId());
        //商户编号
        tmStatRefund.setMchntNo(oriTMTxnOrderDetTrial.getMchntNo());
        //订单币种
        tmStatRefund.setOrderCcy("CNY");
        //营销活动类型 20-手续费减免优惠活动
        tmStatRefund.setMcType(McTypeEnum.MCHNT_FEE_DISCOUNT.getMcTypeCode());
        //交易状态
        tmStatRefund.setTransStatus(TransStatusEnum.TRANS_SUCC.getStatus());
        //业务状态
//        tmStatRefund.setBizStatus(BizStatusEnum.PROCESS_SUCCESS.getBizStatusCode());

        //关联信息
        String relativeDataTrial = oriTMTxnOrderDetTrial.getRelativeData();
        JSONObject relativeDataJsonTrial = JSONObject.parseObject(relativeDataTrial);
        //商户手续费优惠营销活动编号
        String mchntFeeDiscountMcNo = oriTMTxnOrderDetTrial.getMcNo();
        //手续费优惠金额
        String mchntFeeDiscount = oriTMTxnOrderDetTrial.getSubsidy();
        //实收手续费金额
        String mchntFeeActual = new BigDecimal(oriTMTxnOrderDetTrial.getOriginalAmt()).subtract(new BigDecimal(oriTMTxnOrderDetTrial.getSubsidy())).toString();

        //原手续费优惠交易订单金额
        String origOrderAmt = relativeDataJsonTrial.get("origOrderAmt").toString();
        //原手续费优惠交易手续费金额
        String origMchntFee = relativeDataJsonTrial.get("origMchntFee").toString();

        //应收/应退商户手续费
        tmStatRefund.setMchntFee(origMchntFee);
        //订单金额
        tmStatRefund.setOrderAmt(origOrderAmt);

        //手续费减免类营销活动编号
        tmStatRefund.setMcNo(mchntFeeDiscountMcNo);
        //手续费减免类规则顺序号
        tmStatRefund.setRuleIndex(oriTMTxnOrderDetTrial.getRuleIndex());
        //累计退货次数
        tmStatRefund.setRefundCount(CommonConstant.ONE_COMMON_CONSTANT);
        //累计退货订单金额,手续费优惠回退试算的那笔存储的商户退货清算金额
        tmStatRefund.setRefundOrderAmt(relativeDataJsonTrial.get("orderAmt").toString());
        //累计退货手续费金额
        tmStatRefund.setRefundMchntFee(mchntFeeActual);
        //累计退货优惠金额
        tmStatRefund.setRefundSubsidy(mchntFeeDiscount);
        //累计退货银行优惠金额
        tmStatRefund.setRefundBankSubsidy(mchntFeeDiscount);
        //累计退货商户优惠金额
        tmStatRefund.setRefundMchntSubsidy(CommonConstant.ZERO_AMOUNT);
        //创建人
        tmStatRefund.setOprId(CommonConstant.DEFAULT_OPR_ID);
        //创建时间
        tmStatRefund.setCreateTime(newTimeStamp);
        //最后修改人
        tmStatRefund.setLastOprId("");
        //修改时间
        tmStatRefund.setUpdateTime("");
        // 备用字段1
        tmStatRefund.setRemark1("");
        // 备用字段2
        tmStatRefund.setRemark2("");
        // 备用字段3
        tmStatRefund.setRemark3("");
        // 备用字段4
        tmStatRefund.setRemark4("");
        // 备用字段5
        tmStatRefund.setRemark5("");

        //退货统计表中登记的已退货订单金额和本次退货金额(因为是登记所以原表中无数据)
        String alredayRefundAmtAddThis = tmStatRefund.getRefundOrderAmt();
        //更新手续费回退试算订单流水明细,更新手续费优惠订单流水明细，判断当前交易是否在原交易日期的统计周期内，如果在需要更新当前交易的单日统计表
        updateTMTxnOrderDet(oriTMTxnOrder, oriTMTxnOrderDetTrial, tmStatRefund, alredayRefundAmtAddThis);

        //如果是最后一笔退货，更新退货统计表为已全额退款
        if (isLastDeal) {
            tmStatRefund.setBizStatus(BizStatusEnum.PROCESS_REFUNDED.getBizStatusCode());
        } else {
            tmStatRefund.setBizStatus(BizStatusEnum.PROCESS_PARTIALLY_REFUNDED.getBizStatusCode());
        }

        TMStatRefundMapper tmStatRefundMapper = new TMStatRefundMapperImpl();
        int returnCodeTmTxnOrder = tmStatRefundMapper.insertSingleRecordFromTmStatRefund(tmStatRefund);
        if (Database.DBS_SUCCESS != returnCodeTmTxnOrder) {
            rglog.error("登记退货统计表数据失败! INST_ID=<{}>, TRACE_NO=<{}>, ORDER_ID=<{}>",
                    tmStatRefund.getInstId(), tmStatRefund.getSysSeqNum(), tmStatRefund.getOrderId());
            throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
        }
    }

    /**
     * 更新退货统计表，更新手续费回退试算订单流水明细,更新手续费优惠订单流水明细,判断当前交易是否在原交易日期的统计周期内，如果在需要更新当前交易的单日统计表
     *
     * @return void
     * @throws Exception 异常信息
     * @author liujinan
     * @date 2020/5/13
     */
    private void updateTMStatRefund(TMTxnOrder tmTxnOrder, TMTxnOrder tmTxnOrderTrial, TMTxnOrderDet tmTxnOrderDetTrial, TMStatRefund tmStatRefund) throws Exception {
        String newTimeStamp = new SimpleDateFormat(CommonConstant.TIMESTAMP_FORMAT).format(new Date());
        //关联信息
        String relativeData = tmTxnOrderDetTrial.getRelativeData();
        JSONObject relativeDataJsonTrail = JSONObject.parseObject(relativeData);
        //原试算订单金额
        String origOrderAmt = relativeDataJsonTrail.get("orderAmt").toString();
        //手续费优惠金额
        String mchntFeeDiscount = tmTxnOrderDetTrial.getSubsidy();
        //实收手续费金额
        String mchntFeeActual = new BigDecimal(tmTxnOrderDetTrial.getOriginalAmt()).subtract(new BigDecimal(tmTxnOrderDetTrial.getSubsidy())).toString();

        TMStatRefund updateTMStatRefund = new TMStatRefund();
        //机构编码
        updateTMStatRefund.setInstId(tmTxnOrderTrial.getInstId());
        //交易日期
        updateTMStatRefund.setTxnDate(tmTxnOrder.getTxnDate());
        //系统流水号
        updateTMStatRefund.setSysSeqNum(tmTxnOrder.getFrontSeqNum());
        //商户编号
        updateTMStatRefund.setMchntNo(tmTxnOrderDetTrial.getMchntNo());
        //累计退货次数  在sql中计算
        updateTMStatRefund.setRefundCount(CommonConstant.ONE_COMMON_CONSTANT);
        //累计退货订单金额  在sql中计算
        updateTMStatRefund.setRefundOrderAmt(origOrderAmt);
        //累计退货手续费金额  在sql中计算
        updateTMStatRefund.setRefundMchntFee(mchntFeeActual);
        //累计退货优惠金额  在sql中计算
        updateTMStatRefund.setRefundSubsidy(mchntFeeDiscount);
        //修改时间
        updateTMStatRefund.setUpdateTime(newTimeStamp);
        //原支付交易订单金额
        updateTMStatRefund.setOrderAmt(tmStatRefund.getOrderAmt());

        //退货统计表中登记的已退货订单金额和本次退货金额
        String alredayRefundAmtAddThis = (new BigDecimal(tmStatRefund.getRefundOrderAmt())).add(new BigDecimal(origOrderAmt)).toString();
        //更新手续费回退试算订单流水明细,更新手续费优惠订单流水明细,判断当前交易是否在原交易日期的统计周期内，如果在需要更新当前交易的单日统计表
        updateTMTxnOrderDet(tmTxnOrder, tmTxnOrderDetTrial, updateTMStatRefund, alredayRefundAmtAddThis);

        //如果是最后一笔退货，更新退货统计表为已全额退款
        if (isLastDeal) {
            updateTMStatRefund.setBizStatus(BizStatusEnum.PROCESS_REFUNDED.getBizStatusCode());
        } else {
            updateTMStatRefund.setBizStatus(BizStatusEnum.PROCESS_PARTIALLY_REFUNDED.getBizStatusCode());
        }

        TMStatRefundMapper tmStatRefundMapper = new TMStatRefundMapperImpl();
        int returnCodeTmTxnOrder = tmStatRefundMapper.updateSingleRecordFromTmStatRefund(updateTMStatRefund);
        if (CommonConstant.PROCESS_SUCCESS != returnCodeTmTxnOrder) {
            rglog.error("更新退货统计表数据失败! INST_ID=<{}>, TRACE_NO=<{}>, ORDER_ID=<{}>",
                    updateTMStatRefund.getInstId(), updateTMStatRefund.getSysSeqNum(), updateTMStatRefund.getOrderId());
            throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
        }
    }

    /**
     * 更新手续费优惠回退试算订单明细,更新手续费优惠订单明细，判断当前交易是否在原交易日期的统计周期内，如果在需要更新当前交易的单日统计表
     *
     * @return void
     * @throws Exception 异常信息
     * @author liujinan
     * @date 2020/5/14
     */
    private void updateTMTxnOrderDet(TMTxnOrder tmTxnOrder, TMTxnOrderDet tmTxnOrderDetTrial, TMStatRefund tmStatRefund, String alredayRefundAmtAddThis) throws Exception {
        String newTimeStamp = new SimpleDateFormat(CommonConstant.TIMESTAMP_FORMAT).format(new Date());

        TMTxnOrderDetMapper TmTxnOrderDetMapper = new TMTxnOrderDetMapperImpl();
        //设置手续费优惠回退试算业务状态为全额退款，对于试算的那笔交易对应的试算流水，只能是全额退款，对应的原交易可能有多条回退试算
        tmTxnOrderDetTrial.setBizStatus(BizStatusEnum.PROCESS_REFUNDED.getBizStatusCode());
        tmTxnOrderDetTrial.setUpdateTime(newTimeStamp);
        //更新手续费回退试算订单流水明细
        int updateTmTxnOrderDetTrialCode = TmTxnOrderDetMapper.updateTmTxnOrderDetByKey(tmTxnOrderDetTrial);
        if (Database.DBS_SUCCESS != updateTmTxnOrderDetTrialCode) {
            rglog.error("更新手续费优惠回退试算订单明细表数据失败! INST_ID=<{}>, TRACE_NO=<{}>, ORDER_ID=<{}>, MCHNT_NO=<{}>",
                    tmTxnOrderDetTrial.getInstId(), tmTxnOrderDetTrial.getFrontSeqNum(), tmTxnOrderDetTrial.getOrderId(), tmTxnOrderDetTrial.getMchntNo());
            throw new BizException(RespCodeEnum.FAILED_UPDATE_T_M_TXN_ORDER_DET.getRespCode(), RespCodeEnum.FAILED_UPDATE_T_M_TXN_ORDER_DET.getRespDesc());
        }

        TMTxnOrderDet tmTxnOrderDet = new TMTxnOrderDet();
        //订单明细已经退货订单金额,当没有退货记录时，tmStatRefund传入的是即将登记的实体，当有退货记录是传入的是即将更新的实体
        BigDecimal alredayRefundAmt = new BigDecimal(tmStatRefund.getRefundOrderAmt());
        //订单明细订单总金额，退货统计表中的订单总金额即为原手续费优惠订单明细金额
        BigDecimal orderAmt = new BigDecimal(tmStatRefund.getOrderAmt());
        //已退款小于订单总金额，如果不小于应该是等于，不可能大于
        if (new BigDecimal(alredayRefundAmtAddThis).compareTo(orderAmt) < 0) {
            //设置手续费优惠业务状态为部分退款
            tmTxnOrderDet.setBizStatus(BizStatusEnum.PROCESS_PARTIALLY_REFUNDED.getBizStatusCode());
            //设置本笔交易不是最后一笔退款
            isLastDeal = false;
        } else {
            //设置手续费优惠业务状态为全额退款
            tmTxnOrderDet.setBizStatus(BizStatusEnum.PROCESS_REFUNDED.getBizStatusCode());
            //设置本笔交易是最后一笔退款
            isLastDeal = true;
        }
        //机构编码
        tmTxnOrderDet.setInstId(tmTxnOrder.getInstId());
        //交易日期
        tmTxnOrderDet.setTxnDate(tmTxnOrder.getTxnDate());
        //前端流水号
        tmTxnOrderDet.setFrontSeqNum(tmTxnOrder.getFrontSeqNum());
        //商户编号
        tmTxnOrderDet.setMchntNo(tmTxnOrderDetTrial.getMchntNo());
        //营销活动编号
        tmTxnOrderDet.setMcNo(tmTxnOrderDetTrial.getMcNo());
        //更新时间
        tmTxnOrderDet.setUpdateTime(newTimeStamp);
        //规则编号
        tmTxnOrderDet.setRuleIndex(tmTxnOrderDetTrial.getRuleIndex());

        //更新原手续费优惠订单明细
        int updateTmTxnOrderDetCode = TmTxnOrderDetMapper.updateTmTxnOrderDetByKey(tmTxnOrderDet);
        if (Database.DBS_SUCCESS != updateTmTxnOrderDetCode) {
            rglog.error("更新手续费优惠订单明细表数据失败! INST_ID=<{}>, TRACE_NO=<{}>, ORDER_ID=<{}>, MCHNT_NO=<{}>",
                    tmTxnOrderDet.getInstId(), tmTxnOrderDet.getFrontSeqNum(), tmTxnOrderDet.getOrderId(), tmTxnOrderDet.getMchntNo());
            throw new BizException(RespCodeEnum.FAILED_UPDATE_T_M_TXN_ORDER_DET.getRespCode(), RespCodeEnum.FAILED_UPDATE_T_M_TXN_ORDER_DET.getRespDesc());
        }

        //判断当前交易是否在原交易日期的统计周期内，如果在需要更新当前交易的单日统计表
        checkDateAndUpdateStatistical(tmTxnOrderDet, tmTxnOrderDetTrial);
    }

    /**
     * 更新原手续费优惠订单流水，更新手续费回退试算订单流水
     *
     * @return void
     * @throws Exception 异常信息
     * @author liujinan
     * @date 2020/5/14
     */
    private void updateTMTxnOrder(TMTxnOrder tmTxnOrder, TMTxnOrder tmTxnOrderTrial) throws Exception {
        String newTimeStamp = new SimpleDateFormat(CommonConstant.TIMESTAMP_FORMAT).format(new Date());

        Boolean isOrderFullRefund = true;
        /* 查询原交易订单明细信息 */
        List<TMTxnOrderDet> tmTxnOrderDetList = getOriginalTransactionOrderDetailInfo(globalInstId, tmTxnOrder.getTxnDate(), tmTxnOrder.getFrontSeqNum());
        if (null == tmTxnOrderDetList || tmTxnOrderDetList.isEmpty()) {
            rglog.error("机构<{}>在<{}>的原交易订单明细信息<{}>失败!", globalInstId, tmTxnOrder.getTxnDate(), tmTxnOrder.getFrontSeqNum());
            throw new BizException(RespCodeEnum.FAILED_TO_CHECK_ORIGINAL_TXNDET_INFO_ERROR.getRespCode(), RespCodeEnum.FAILED_TO_CHECK_ORIGINAL_TXNDET_INFO_ERROR.getRespDesc());
        }
        //循环遍历原订单流水对应的订单明细信息，如果状态都为已全额退款，则更新原交易流水为已全额退款，否则为部分退款
        for (TMTxnOrderDet tMTxnOrderDet : tmTxnOrderDetList) {
            if (!BizStatusEnum.PROCESS_REFUNDED.getBizStatusCode().equals(tMTxnOrderDet.getBizStatus())) {
                isOrderFullRefund = false;
                break;
            }
        }
        if (isOrderFullRefund) {
            /* 全额退款,报文内容和原支付交易内容相同 */
            tmTxnOrder.setBizStatus(BizStatusEnum.PROCESS_REFUNDED.getBizStatusCode());
        } else {
            /* 部分退款,优惠部分为0,其他和退货金额相同 */
            tmTxnOrder.setBizStatus(BizStatusEnum.PROCESS_PARTIALLY_REFUNDED.getBizStatusCode());
        }
        tmTxnOrder.setUpdateTime(newTimeStamp);

        //更新原手续费优惠订单流水
        int updateTxnOrderBizStatusReturnCode = updateTxnOrderBizStatusInfo(tmTxnOrder);
        if (CommonConstant.PROCESS_SUCCESS != updateTxnOrderBizStatusReturnCode) {
            rglog.error("更新订单流水表失败,流水号<{}>!", tmTxnOrder.getMchntNo(), tmTxnOrder.getFrontSeqNum());
            throw new BizException(RespCodeEnum.FAILED_UPDATE_T_M_TXN_ORDER.getRespCode(), RespCodeEnum.FAILED_UPDATE_T_M_TXN_ORDER.getRespDesc());
        }

        //手续费优惠回退试算设置业务状态，金额只能为全额
        tmTxnOrderTrial.setBizStatus(BizStatusEnum.PROCESS_REFUNDED.getBizStatusCode());
        tmTxnOrderTrial.setTransStatus(TransStatusEnum.TRANS_SUCC.getStatus());
        tmTxnOrderTrial.setUpdateTime(newTimeStamp);
        //更新手续费优惠回退试算订单流水
        int updateTxnOrderTrialBizStatusReturnCode = updateTxnOrderBizStatusInfo(tmTxnOrderTrial);
        if (CommonConstant.PROCESS_SUCCESS != updateTxnOrderTrialBizStatusReturnCode) {
            rglog.error("更新订单流水表失败,流水号<{}>!", tmTxnOrderTrial.getFrontSeqNum());
            throw new BizException(RespCodeEnum.FAILED_UPDATE_T_M_TXN_ORDER.getRespCode(), RespCodeEnum.FAILED_UPDATE_T_M_TXN_ORDER.getRespDesc());
        }
    }


    /**
     * 商户手续费优惠回退——未经试算直接回退的使用
     *
     * @param comboMchntFeeDiscountRefundRequest 请求报文提
     * @throws Exception 异常信息
     * @author liujinan
     * @date 2020/5/11 10:24
     */
    private void processMchntFeeDiscountRefundTrialProcedure(ComboMchntFeeDiscountRefundRequest comboMchntFeeDiscountRefundRequest, TMTxnOrder tmTxnOrderOrig,
                                                             List<TMTxnOrderDet> tmTxnOrderDetListOrig, ComboMchntFeeDiscountRefundResponse comboMchntFeeDiscountRefundResponse) throws Exception {

        List<PaymentReturnOrderMchntFeeDiscountInfoBean> returnFeeDiscountInfoBeanList = new ArrayList<>();

        List<TMTxnOrderDet> tMTxnOrderDetListThisTime = new ArrayList<>();

        for (PaymentReturnOrderMchntFeeDiscountInfoBean feeDiscountInfoBean : comboMchntFeeDiscountRefundRequest.getFeeReturnOrderList()) {
            int returnCode;
            String instId = tmTxnOrderOrig.getInstId();
            String transDate = tmTxnOrderOrig.getTxnDate();
            String mchntNo = feeDiscountInfoBean.getMchntNo();
            String orderId = tmTxnOrderOrig.getOrderId();
            //通过商户号获取原交易明细
            List<TMTxnOrderDet> tmTxnOrderDetListMdfOrig = tmTxnOrderDetListOrig.stream().filter(item -> ((McTypeEnum.MC_TYPE_MFD.getMcTypeCode().equals(item.getMcType().substring(0, 1))) && mchntNo.equals(item.getMchntNo()))).collect(Collectors.toList());

            if (null != tmTxnOrderDetListMdfOrig && !tmTxnOrderDetListMdfOrig.isEmpty()) {
                //判断记录条数
                if (CommonConstant.ONE != tmTxnOrderDetListMdfOrig.size()) {
                    //每个合并支付订单应该只有一条记录，有多条说明是异常情况,流程结束
                    rglog.error("机构<{}>在<{}>的商户<{}>的支付订单明细有多条,异常!", tmTxnOrderOrig.getInstId(), tmTxnOrderOrig.getTxnDate(), feeDiscountInfoBean.getMchntNo());
                    throw new BizException(RespCodeEnum.MULTI_ORDER_DETAIL_FOR_SINGLE_MCHNT_ERROR.getRespCode(), RespCodeEnum.MULTI_ORDER_DETAIL_FOR_SINGLE_MCHNT_ERROR.getRespDesc());
                }
                //商户手续费优惠回退处理流程－逐个订单明细处理
                returnCode = processSingleMchntFeeDiscountRefundTrialProcedure(comboMchntFeeDiscountRefundRequest, feeDiscountInfoBean, tmTxnOrderOrig,
                        tmTxnOrderDetListMdfOrig.get(CommonConstant.ZERO), tMTxnOrderDetListThisTime);

                if (CommonConstant.PROCESS_SUCCESS != returnCode) {
                    rglog.error("机构<{}>在<{}>的订单<{}>中商户<{}>的手续费回退失败!", instId, transDate, orderId, mchntNo);
                    throw new BizException(RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespCode(), RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespDesc());
                }
            } else {
                // 未找到对应商户的手续费优惠信息，不处理！
                rglog.error("机构<{}>在<{}>的商户<{}>未参加任何商户手续费优惠类营销活动，不进行优惠回退!", instId, transDate, mchntNo);
                feeDiscountInfoBean.setMchntFeeActual(feeDiscountInfoBean.getMchntFeeReceivable());
                feeDiscountInfoBean.setMchntFeeDiscount(CommonConstant.ZERO_COMMON_CONSTANT);
            }
            //将明细信息添加到返回响应List
            returnFeeDiscountInfoBeanList.add(feeDiscountInfoBean);
        }
        //处理完成后插入订单明细，可能多条
        recordTxnOrderDetList(tMTxnOrderDetListThisTime);
        //处理完成后登记订单流水
        rglog.info("登记交易订单流水<{}>开始...", tmTxnOrderOrig.getFrontSeqNum());
        TMTxnOrder tmTxnOrderthisTime = recordTxnOrder(comboMchntFeeDiscountRefundRequest, tmTxnOrderOrig, returnFeeDiscountInfoBeanList);

        rglog.info("更新原交易订单流水<{}>开始...", tmTxnOrderOrig.getFrontSeqNum());
        //处理完成后更新原交易流水
        updateTMTxnOrderNoTrail(tmTxnOrderOrig, tmTxnOrderthisTime);

        //设置返回列表信息
        comboMchntFeeDiscountRefundResponse.setFeeReturnOrderList(returnFeeDiscountInfoBeanList);
    }

    /**
     * 单个商户手续费优惠订单明细回退试算——未经试算直接回退的使用
     *
     * @param feeDiscountInfoBean 接口上送的手续费优惠回退订单信息
     * @return int
     * @throws Exception 异常信息
     * @author liujinan
     * @date 2020/5/11 19:17
     */
    private int processSingleMchntFeeDiscountRefundTrialProcedure(ComboMchntFeeDiscountRefundRequest comboMchntFeeDiscountRefundRequest, PaymentReturnOrderMchntFeeDiscountInfoBean feeDiscountInfoBean,
                                                                  TMTxnOrder tmTxnOrderOrig, TMTxnOrderDet tmTxnOrderDetOrig, List<TMTxnOrderDet> tMTxnOrderDetListThisTime) throws Exception {
        // 通过原订单金额和本次退款订单金额判断是全额退货还是部分退货
        //原手续费优惠流水中relative_data(关联信息)字段中取值
        String relativeData = tmTxnOrderDetOrig.getRelativeData();
        JSONObject relativeDataJson = JSONObject.parseObject(relativeData);

        //原商户订单明细金额
        BigDecimal origOrderAmt = new BigDecimal(relativeDataJson.get("orderAmt").toString());

        //本次上送的退款订单金额
        BigDecimal refundOrderAmt = new BigDecimal(feeDiscountInfoBean.getMchntSettleAmt());

        if (CommonConstant.IS_EQUAL_TO == origOrderAmt.compareTo(refundOrderAmt)) {
            //全额退款场景
            fullyMchntFeeDiscountRefundTrial(comboMchntFeeDiscountRefundRequest, feeDiscountInfoBean, tmTxnOrderOrig, tmTxnOrderDetOrig, tMTxnOrderDetListThisTime);
        } else {
            //部分退款场景
            partMchntFeeDiscountRefundTrial(comboMchntFeeDiscountRefundRequest, feeDiscountInfoBean, tmTxnOrderOrig, tmTxnOrderDetOrig, tMTxnOrderDetListThisTime);
        }
        return CommonConstant.PROCESS_SUCCESS;
    }

    /**
     * 计算部分退款商户，商户应退优惠手续费
     *
     * @param feeDiscountInfoBean 接口上送的手续费优惠回退订单信息
     * @throws Exception 异常信息
     * @author liujinan
     * @date 2020/6/5 09:58
     */
    private int partMchntFeeDiscountRefundTrial(ComboMchntFeeDiscountRefundRequest comboMchntFeeDiscountRefundRequest,
                                                PaymentReturnOrderMchntFeeDiscountInfoBean feeDiscountInfoBean, TMTxnOrder tmTxnOrderOrig,
                                                TMTxnOrderDet tmTxnOrderDetOrig, List<TMTxnOrderDet> tMTxnOrderDetListThisTime) throws Exception {

        String instId = tmTxnOrderOrig.getInstId();
        String transDate = tmTxnOrderOrig.getTxnDate();
        String mchntNo = tmTxnOrderDetOrig.getMchntNo();
        String traceNo = tmTxnOrderOrig.getFrontSeqNum();
        //关联信息
        String relativeData = tmTxnOrderDetOrig.getRelativeData();
        JSONObject relativeDataJson = JSONObject.parseObject(relativeData);

        //获取已退货信息
        TMStatRefundMapper tmStatRefundMapper = new TMStatRefundMapperImpl();
        TMStatRefund tmStatRefund = tmStatRefundMapper.selectSingleRecordFromTMStatRefund(instId, transDate, traceNo, mchntNo);

        //原手续费优惠流水中relative_data(关联信息)字段中取值
        //商户手续费优惠类型
        String discountType = relativeDataJson.get("discountType").toString();
        //优惠力度
        BigDecimal discount = new BigDecimal(relativeDataJson.get("discount").toString());
        //商户应收手续费金额
        BigDecimal mchntFeeReceivable = new BigDecimal(relativeDataJson.get("mchntFeeReceivable").toString());
        //商户应收手续费费率
        BigDecimal mchntFeeReceivableRate = BigDecimal.ZERO;
        Object mchntFeeReceivableRateObject = relativeDataJson.get("mchntFeeReceivableRate");
        if (null == mchntFeeReceivableRateObject) {
            //获取原支付交易的源系统标识，迁移数据固定为“SJQY”
            String msgSrcId = tmTxnOrderOrig.getMsgSrcId();
            //如果是迁移的数据，没有feeInputMode值正常，迁移数据都为
            if (CommonConstant.SHUJUQIANYI.equals(msgSrcId)) {
                rglog.info("本次退货原交易流水<{}> 为老平台迁移数据，原交易订单明细中mchntFeeReceivableRate为空!", tmTxnOrderOrig.getFrontSeqNum());
            } else {
                //不是迁移数据时，如果字段为空，则原交易存在问题
                rglog.error("本次退货原交易流水<{}> 原交易不是迁移数据，交易订单明细中mchntFeeReceivableRate为空，异常!", tmTxnOrderOrig.getFrontSeqNum());
                throw new BizException(RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespCode(), RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespDesc());
            }
        } else {
            /* 商户应收手续费费率 */
            mchntFeeReceivableRate = new BigDecimal(mchntFeeReceivableRateObject.toString()).setScale(CommonConstant.DECIMAL_SCALE_FIVE, RoundingMode.HALF_UP);
        }

        //实收手续费金额
        BigDecimal mchntFeeActual = new BigDecimal(tmTxnOrderDetOrig.getOriginalAmt()).subtract(new BigDecimal(tmTxnOrderDetOrig.getSubsidy()));

        //手续费收取方式,赋默认值“手工输入按比率”
        String feeInputMode = CommonConstant.FEE_MODE_RATE;
        Object feeInputModeObject = relativeDataJson.get("feeInputMode");
        if (null == feeInputModeObject) {
            //获取原支付交易的源系统标识，迁移数据固定为“SJQY”
            String msgSrcId = tmTxnOrderOrig.getMsgSrcId();
            //如果是迁移的数据，没有feeInputMode值正常
            if (CommonConstant.SHUJUQIANYI.equals(msgSrcId)) {
                rglog.info("本次退货交易流水<{}> 为老平台迁移数据，原交易订单明细中feeInputMode为空!", tmTxnOrderOrig.getFrontSeqNum());
            } else {
                //不是迁移数据时，如果字段为空，则原交易存在问题
                rglog.error("本次退货原交易流水<{}> 原交易不是迁移数据，交易订单明细中feeInputMode为空，异常!", tmTxnOrderOrig.getFrontSeqNum());
                throw new BizException(RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespCode(), RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespDesc());
            }
        } else {
            feeInputMode = feeInputModeObject.toString();
        }

        //接口上送的本次应退手续费
        BigDecimal thisTimeMchntFeeReceivable = new BigDecimal(feeDiscountInfoBean.getMchntFeeReceivable());

        //原商户订单明细金额
        BigDecimal origOrderAmt = new BigDecimal(relativeDataJson.get("orderAmt").toString());

        //本次上送的退款订单金额
        BigDecimal refundOrderAmt = new BigDecimal(feeDiscountInfoBean.getMchntSettleAmt());

        //本次退款记录的,手续费优惠金额,实退手续费金额
        BigDecimal refundmchntFeeDiscount = BigDecimal.ZERO;
        BigDecimal refundMchntFeeActual = BigDecimal.ZERO;

        //剩余消费金额
        BigDecimal residueOrderAmt = BigDecimal.ZERO;
        //剩余消费金额应收手续费
        BigDecimal residueFeeActual = BigDecimal.ZERO;

        //已退货订单总金额  本次退货订单金额＋已退货订单总金额
        BigDecimal refundOrderAmtTotal = BigDecimal.ZERO;
        //累计实退手续费金额
        BigDecimal alredayRefundCharge = BigDecimal.ZERO;

        //1000
        BigDecimal thousand = new BigDecimal(CommonConstant.THOUSAND);

        if (null == tmStatRefund) {
            rglog.info("未取到退货记录，说明之前未有过退货订单,本次为第一次部分退款!");
            //剩余消费金额 ＝ 原商户清算金额（有可能与原订单明细订单金额相同)－商户退款清算金额(本次退货订单金额)
            residueOrderAmt = origOrderAmt.subtract(refundOrderAmt);
            //累计实退手续费金额
            alredayRefundCharge = BigDecimal.ZERO.setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
            //已退货订单总金额
            refundOrderAmtTotal = BigDecimal.ZERO.setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
        } else {
            //剩余消费金额 ＝ 原商户清算金额（有可能与原订单明细订单金额相同)－累计退货订单金额-本次退货订单金额
            residueOrderAmt = origOrderAmt.subtract(new BigDecimal(tmStatRefund.getRefundOrderAmt())).subtract(refundOrderAmt);
            //累计实退手续费金额
            alredayRefundCharge = new BigDecimal(tmStatRefund.getRefundMchntFee()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
            //已退货订单总金额
            refundOrderAmtTotal = new BigDecimal(tmStatRefund.getRefundOrderAmt()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
        }
        //本次退货订单金额＋已退货订单总金额 ,用于判断是否是最后一笔退款
        BigDecimal afterOrderAmt = refundOrderAmt.add(refundOrderAmtTotal).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);

        if (afterOrderAmt.compareTo(origOrderAmt) > 0) {
            rglog.error("订单流水号<{}>手续费回退失败,总退款金额超过原订单金额!", traceNo);
            throw new BizException(RespCodeEnum.FAILED_TO_REFUND_TRIAL_EXCEED.getRespCode(), RespCodeEnum.FAILED_TO_REFUND_TRIAL_EXCEED.getRespDesc());
        }

        switch (feeInputMode) {
            case CommonConstant.FEE_MODE_LADDER:
                // 使用现有费率
                rglog.error("商户<{}>,手续费收取方式<{}>-使用现有费率,不支持配置费率模板方式的商户手续费优惠计算!!", feeDiscountInfoBean.getMchntNo(), feeInputMode);
                refundmchntFeeDiscount = refundmchntFeeDiscount;
                refundMchntFeeActual = thisTimeMchntFeeReceivable;
                break;
            case CommonConstant.FEE_MODE_RATE:
                // 手工输入按比率
                switch (discountType) {
                    //手续费全免
                    case CommonConstant.MCHNT_FEE_FREE:
                        rglog.info("商户<{}>,手续费收取方式<{}>-手工输入按比率,商户手续费优惠类型<{}>-免手续费!", feeDiscountInfoBean.getMchntNo(), feeInputMode, discountType);
                        refundMchntFeeActual = mchntFeeActual.subtract(alredayRefundCharge);
                        refundmchntFeeDiscount = thisTimeMchntFeeReceivable.subtract(refundMchntFeeActual);
                        break;
                    //费率打折,实收 = 订单金额*应收费率*折扣,优惠=应收-实收
                    case CommonConstant.MCHNT_FEE_DISCOUNT:
                        rglog.info("商户<{}>,手续费收取方式<{}>-手工输入按比率,商户手续费优惠类型<{}>-费率打折!", feeDiscountInfoBean.getMchntNo(), feeInputMode, discountType);
                        if (afterOrderAmt.compareTo(origOrderAmt) == 0) {
                            //本次是最后一笔退款,实退为当初实收的减已经退的
                            refundMchntFeeActual = mchntFeeActual.subtract(alredayRefundCharge);
                            refundmchntFeeDiscount = thisTimeMchntFeeReceivable.subtract(refundMchntFeeActual);
                        } else {
                            //剩余消费订单金额应收手续费
                            residueFeeActual = residueOrderAmt.multiply(mchntFeeReceivableRate).divide(thousand).multiply(discount).divide(BigDecimal.TEN).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                            //实退手续费为  消费时实收手续费-累计实退手续费-剩余消费金额应收手续费
                            refundMchntFeeActual = mchntFeeActual.subtract(alredayRefundCharge).subtract(residueFeeActual);
                            refundmchntFeeDiscount = thisTimeMchntFeeReceivable.subtract(refundMchntFeeActual);
                        }
                        break;
                    // 固定费率,实收=订单金额*优惠费率,优惠=应收-实收
                    case CommonConstant.MCHNT_FEE_FIXED_RATE:
                        rglog.info("商户<{}>,手续费收取方式<{}>-手工输入按比率,商户手续费优惠类型<{}>-固定费率!", feeDiscountInfoBean.getMchntNo(), feeInputMode, discountType);
                        if (afterOrderAmt.compareTo(origOrderAmt) == 0) {
                            //本次是最后一笔退款,实退为当初实收的减已经退的
                            refundMchntFeeActual = mchntFeeActual.subtract(alredayRefundCharge);
                            refundmchntFeeDiscount = thisTimeMchntFeeReceivable.subtract(refundMchntFeeActual);
                        } else {
                            //剩余消费订单金额应收手续费
                            residueFeeActual = residueOrderAmt.multiply(discount).divide(thousand).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                            //实退手续费为  消费时实收手续费-累计实退手续费-剩余消费金额应收手续费
                            refundMchntFeeActual = mchntFeeActual.subtract(alredayRefundCharge).subtract(residueFeeActual);
                            refundmchntFeeDiscount = thisTimeMchntFeeReceivable.subtract(refundMchntFeeActual);
                        }
                        break;
                    default:
                        rglog.info("商户<{}>,手续费收取方式<{}>-手工输入按比率,商户手续费优惠类型<{}>-优惠类型异常!", feeDiscountInfoBean.getMchntNo(), feeInputMode, discountType);
                        refundMchntFeeActual = BigDecimal.ZERO;
                        refundmchntFeeDiscount = BigDecimal.ZERO;
                        break;
                }
                break;
            // 手工输入按固定金额
            case CommonConstant.FEE_MODE_FIXED_AMT:
                switch (discountType) {
                    // 手续费全免
                    case CommonConstant.MCHNT_FEE_FREE:
                        rglog.info("商户<{}>,手续费收取方式<{}>-手工输入按固定金额,商户手续费优惠类型<{}>-免手续费!", feeDiscountInfoBean.getMchntNo(), feeInputMode, discountType);
                        //本次是最后一笔退款
                        refundMchntFeeActual = mchntFeeActual.subtract(alredayRefundCharge);
                        refundmchntFeeDiscount = thisTimeMchntFeeReceivable.subtract(refundMchntFeeActual);
                        break;
                    //手工输入按固定金额,不支持费率打折或固定费率的优惠方式
                    case CommonConstant.MCHNT_FEE_DISCOUNT:
                    case CommonConstant.MCHNT_FEE_FIXED_RATE:
                        rglog.error("应收手续费费率是固定金额,不可使用费率打折或固定费率的商户手续费优惠方式,手续费全免在最后一次退款时计算!");
                        refundMchntFeeActual = BigDecimal.ZERO;
                        refundmchntFeeDiscount = BigDecimal.ZERO;
                        break;
                    default:
                        rglog.info("商户<{}>,手续费收取方式<{}>-手工输入按固定金额,商户手续费优惠类型<{}>-优惠类型异常!", feeDiscountInfoBean.getMchntNo(), feeInputMode, discountType);
                        refundMchntFeeActual = BigDecimal.ZERO;
                        refundmchntFeeDiscount = BigDecimal.ZERO;
                        break;
                }
                break;
            // 手工输入按比率+封顶值
            case CommonConstant.FEE_MODE_RATE_AMT:
                switch (discountType) {
                    //手续费全免
                    case CommonConstant.MCHNT_FEE_FREE:
                        rglog.info("商户<{}>,手续费收取方式<{}>-手工输入按比率+封顶值,商户手续费优惠类型<{}>-免手续费!", feeDiscountInfoBean.getMchntNo(), feeInputMode, discountType);
                        //本次是最后一笔退款
                        refundMchntFeeActual = mchntFeeActual.subtract(alredayRefundCharge);
                        refundmchntFeeDiscount = thisTimeMchntFeeReceivable.subtract(refundMchntFeeActual);
                        break;
                    //discount_type= 1-费率打折  实收=min(订单金额*费率*折扣,应收), 优惠=应退-实退
                    case CommonConstant.MCHNT_FEE_DISCOUNT:
                        rglog.info("商户<{}>,手续费收取方式<{}>-手工输入按比率+封顶值,商户手续费优惠类型<{}>-费率打折!", feeDiscountInfoBean.getMchntNo(), feeInputMode, discountType);
                        if (afterOrderAmt.compareTo(origOrderAmt) == 0) {
                            //本次是最后一笔退款,实退为当初实收的减已经退的
                            refundMchntFeeActual = mchntFeeActual.subtract(alredayRefundCharge);
                            refundmchntFeeDiscount = thisTimeMchntFeeReceivable.subtract(refundMchntFeeActual);
                        } else {
                            //剩余消费订单金额应收手续费
                            residueFeeActual = residueOrderAmt.multiply(mchntFeeReceivableRate).divide(thousand).multiply(discount).divide(BigDecimal.TEN).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                            residueFeeActual = residueFeeActual.min(mchntFeeReceivable);
                            //实退手续费为  消费时实收手续费-累计实退手续费-剩余消费金额应收手续费
                            refundMchntFeeActual = mchntFeeActual.subtract(alredayRefundCharge).subtract(residueFeeActual);
                            refundmchntFeeDiscount = thisTimeMchntFeeReceivable.subtract(refundMchntFeeActual);
                        }
                        break;
                    // discount_type= 2-固定费率 min(订单金额orderAmt*discount, (手续费优惠上限fee_discount_limit-累计优惠金额total_amt_acc)
                    case CommonConstant.MCHNT_FEE_FIXED_RATE:
                        rglog.info("商户<{}>,手续费收取方式<{}>-手工输入按比率+封顶值,商户手续费优惠类型<{}>-固定费率!", feeDiscountInfoBean.getMchntNo(), feeInputMode, discountType);
                        if (afterOrderAmt.compareTo(origOrderAmt) == 0) {
                            //本次是最后一笔退款,实退为当初实收的减已经退的
                            refundMchntFeeActual = mchntFeeActual.subtract(alredayRefundCharge);
                            refundmchntFeeDiscount = thisTimeMchntFeeReceivable.subtract(refundMchntFeeActual);
                        } else {
                            //剩余消费订单金额应收手续费
                            residueFeeActual = residueOrderAmt.multiply(discount).divide(thousand).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                            residueFeeActual = residueFeeActual.min(mchntFeeReceivable);
                            //实退手续费为  消费时实收手续费-累计实退手续费-剩余消费金额应收手续费
                            refundMchntFeeActual = mchntFeeActual.subtract(alredayRefundCharge).subtract(residueFeeActual);
                            refundmchntFeeDiscount = thisTimeMchntFeeReceivable.subtract(refundMchntFeeActual);
                        }
                        break;
                    default:
                        rglog.info("商户<{}>,手续费收取方式<{}>-手工输入按比率+封顶值,商户手续费优惠类型<{}>-优惠类型异常!", feeDiscountInfoBean.getMchntNo(), feeInputMode, discountType);
                        refundMchntFeeActual = BigDecimal.ZERO;
                        refundmchntFeeDiscount = BigDecimal.ZERO;
                        break;
                }
                break;
            default:
                rglog.info("手续费收取方式错误！");
                refundMchntFeeActual = BigDecimal.ZERO;
                refundmchntFeeDiscount = BigDecimal.ZERO;
                break;
        }

        feeDiscountInfoBean.setMchntFeeDiscount(refundmchntFeeDiscount.setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).toString());
        feeDiscountInfoBean.setMchntFeeActual(refundMchntFeeActual.setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).toString());

        boolean isLastRefund = false;
        if (afterOrderAmt.compareTo(origOrderAmt) == 0) {
            //如果是最后一笔退款，则置为true
            isLastRefund = true;
        }
        //生成订单明细信息
        TMTxnOrderDet insertTMTxnOrderDet = generateTxnOrderDetail(comboMchntFeeDiscountRefundRequest, tmTxnOrderDetOrig, feeDiscountInfoBean, relativeDataJson, isLastRefund);

        //如果手续费回退的交易有手续费优惠值，则登记订单明细表，如果没有则不登记
        if (new BigDecimal(insertTMTxnOrderDet.getSubsidy()).compareTo(BigDecimal.ZERO) > CommonConstant.ZERO
                || CommonConstant.ONE_COMMON_CONSTANT.equals(insertTMTxnOrderDet.getRemark1())) {
            //加入待插入订单明细表list
            tMTxnOrderDetListThisTime.add(insertTMTxnOrderDet);

            globalTMTxnOrderDetList.add(insertTMTxnOrderDet);
        }

        rglog.info("商户<{}>更新原交易订单明细<{}>信息...!", tmTxnOrderDetOrig.getMchntNo(), tmTxnOrderDetOrig.getFrontSeqNum());
        //更新原交易订单明细  内部有是否是最后一笔退货的判断，根据内部的赋值判断是否需要更新统计表交易笔数
        updateTMTxnOrderDetNotrail(tmTxnOrderOrig, tmTxnOrderDetOrig, tmStatRefund, refundOrderAmt.toString());

        if (null == tmStatRefund) {
            rglog.info("未取到交易流水<{}>退货记录，说明之前未有过退货订单,本次插入一条记录!", tmTxnOrderDetOrig.getFrontSeqNum());
            //登记退货统计表,判断当前交易是否在原交易日期的统计周期内，如果在需要更新当前交易的单日统计表
            recordTMStatRefundNoTrail(tmTxnOrderOrig, insertTMTxnOrderDet);
        } else {
            rglog.info("取到交易流水<{}>退货记录，说明之前有过退货订单,本次更新记录!", tmTxnOrderDetOrig.getFrontSeqNum());
            //更新退货统计表,判断当前交易是否在原交易日期的统计周期内，如果在需要更新当前交易的单日统计表
            updateTMStatRefundNoTrail(tmTxnOrderOrig, insertTMTxnOrderDet, tmStatRefund);
        }

        return CommonConstant.ZERO;
    }

    /**
     * 处理商户手续费营销活动全额回退——未经试算直接回退的使用
     *
     * @return void
     * @throws Exception 异常信息
     * @author liujinan
     * @date 2020/4/27 09:51
     */
    private void fullyMchntFeeDiscountRefundTrial(ComboMchntFeeDiscountRefundRequest comboMchntFeeDiscountRefundRequest,
                                                  PaymentReturnOrderMchntFeeDiscountInfoBean feeDiscountInfoBean, TMTxnOrder tmTxnOrderOrig,
                                                  TMTxnOrderDet tmTxnOrderDetOrig, List<TMTxnOrderDet> tMTxnOrderDetListThisTime) throws Exception {
        String instId = tmTxnOrderOrig.getInstId();
        String transDate = tmTxnOrderOrig.getTxnDate();
        String mchntNo = tmTxnOrderDetOrig.getMchntNo();
        String traceNo = tmTxnOrderOrig.getFrontSeqNum();
        //本次退款记录的,手续费优惠金额,实退手续费金额
        BigDecimal refundmchntFeeDiscount = BigDecimal.ZERO;
        BigDecimal refundMchntFeeActual = BigDecimal.ZERO;

        //获取已退货信息
        TMStatRefundMapper tmStatRefundMapper = new TMStatRefundMapperImpl();
        TMStatRefund tmStatRefund = tmStatRefundMapper.selectSingleRecordFromTMStatRefund(instId, transDate, traceNo, mchntNo);

        //关联信息
        String relativeData = tmTxnOrderDetOrig.getRelativeData();
        JSONObject relativeDataJson = JSONObject.parseObject(relativeData);

        //判断是否符合全额回退
        if (null == tmStatRefund) {
            rglog.info("商户<{}>,交易流水<{}>未取到退货记录，之前未有过退货订单,本次可以全额退款", mchntNo, traceNo);
            //原手续费优惠流水中relative_data(关联信息)字段中取值
            //计算实退手续费金额 ＝ 手续费优惠时实收手续费
            refundMchntFeeActual = new BigDecimal(tmTxnOrderDetOrig.getOriginalAmt()).subtract(new BigDecimal(tmTxnOrderDetOrig.getSubsidy()));
            //本次优惠手续费 ＝ 应退手续费 － 实退手续费
            refundmchntFeeDiscount = new BigDecimal(feeDiscountInfoBean.getMchntFeeReceivable()).subtract(refundMchntFeeActual).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);

            feeDiscountInfoBean.setMchntFeeDiscount(refundmchntFeeDiscount.toString());
            feeDiscountInfoBean.setMchntFeeActual(refundMchntFeeActual.toString());
        } else {
            //累计退货订单金额
            BigDecimal refundOrderAmt = new BigDecimal(tmStatRefund.getRefundOrderAmt());
            if (BigDecimal.ZERO.compareTo(refundOrderAmt) < CommonConstant.ZERO) {
                rglog.info("商户<{}>,交易流水<{}>已有退款订单，本次不能全额退款！", mchntNo, traceNo);
                throw new BizException(RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespCode(), RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespDesc());
            }
        }
        //生成订单明细信息
        TMTxnOrderDet insertTMTxnOrderDet = generateTxnOrderDetail(comboMchntFeeDiscountRefundRequest, tmTxnOrderDetOrig, feeDiscountInfoBean, relativeDataJson, true);

        //如果手续费回退的交易有手续费优惠值，则登记订单明细表，如果没有则不登记（使用remark1标识，此订单虽然没有手续费优惠但是需要登记订单明细（有优惠交易金额））
        if (new BigDecimal(insertTMTxnOrderDet.getSubsidy()).compareTo(BigDecimal.ZERO) > CommonConstant.ZERO
                || CommonConstant.ONE_COMMON_CONSTANT.equals(insertTMTxnOrderDet.getRemark1())) {
            //加入待插入订单明细表list
            tMTxnOrderDetListThisTime.add(insertTMTxnOrderDet);

            globalTMTxnOrderDetList.add(insertTMTxnOrderDet);
        }

        rglog.info("商户<{}>更新原交易明细<{}>...!", mchntNo, traceNo);
        //更新原交易订单明细
        updateTMTxnOrderDetNotrail(tmTxnOrderOrig, tmTxnOrderDetOrig, tmStatRefund, feeDiscountInfoBean.getMchntSettleAmt());

        rglog.info("商户<{}>,交易流水<{}>未取到退货记录，说明之前未有过退货订单,本次插入一条记录!", mchntNo, traceNo);
        //登记退货统计表,判断当前交易是否在原交易日期的统计周期内，如果在需要更新当前交易的单日统计表
        recordTMStatRefundNoTrail(tmTxnOrderOrig, insertTMTxnOrderDet);
    }

    /**
     * 登记订单明细表
     *
     * @param comboMchntFeeDiscountRefundRequest
     * @param tmTxnOrderDetOrig
     * @return void
     * @throws Exception 异常信息
     * @author liujinan
     * @date 2020/5/13
     */
    private TMTxnOrderDet generateTxnOrderDetail(ComboMchntFeeDiscountRefundRequest comboMchntFeeDiscountRefundRequest, TMTxnOrderDet tmTxnOrderDetOrig,
                                                 PaymentReturnOrderMchntFeeDiscountInfoBean feeDiscountInfoBean, JSONObject oriRelativeDataJson, boolean isLastRefund) throws Exception {
        String newTimeStamp = new SimpleDateFormat(CommonConstant.TIMESTAMP_FORMAT).format(new Date());

        TMTxnOrderDet refundTmTxnOrderDet = new TMTxnOrderDet();
        // 机构编码
        refundTmTxnOrderDet.setInstId(comboMchntFeeDiscountRefundRequest.getHeader().getInstId());
        // 交易日期
        refundTmTxnOrderDet.setTxnDate(comboMchntFeeDiscountRefundRequest.getHeader().getTransDate());
        //前端流水号
        refundTmTxnOrderDet.setFrontSeqNum(comboMchntFeeDiscountRefundRequest.getHeader().getTraceNo());
        //订单号
        refundTmTxnOrderDet.setOrderId(comboMchntFeeDiscountRefundRequest.getMchntOrderId());
        //商户编号
        refundTmTxnOrderDet.setMchntNo(tmTxnOrderDetOrig.getMchntNo());
        //用户编号
        refundTmTxnOrderDet.setUserId(tmTxnOrderDetOrig.getUserId());
        //核对状态
        refundTmTxnOrderDet.setVerifyStatus(CommonConstant.VERIFY_STATUS_INIT);
        //业务状态 00:业务处理成功
        refundTmTxnOrderDet.setBizStatus(BizStatusEnum.PROCESS_SUCCESS.getBizStatusCode());
        //营销活动类型 20:手续费减免活动
        refundTmTxnOrderDet.setMcType(McTypeEnum.MCHNT_FEE_DISCOUNT.getMcTypeCode());
        //原始金额
        refundTmTxnOrderDet.setOriginalAmt(new BigDecimal(feeDiscountInfoBean.getMchntFeeReceivable()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).toString());
        //营销活动编号
        refundTmTxnOrderDet.setMcNo(tmTxnOrderDetOrig.getMcNo());
        //规则顺序号
        refundTmTxnOrderDet.setRuleIndex(tmTxnOrderDetOrig.getRuleIndex());
        //总补贴金额
        refundTmTxnOrderDet.setSubsidy(feeDiscountInfoBean.getMchntFeeDiscount());
        //机构补贴金额
        refundTmTxnOrderDet.setBankSubsidy(feeDiscountInfoBean.getMchntFeeDiscount());
        //商户补贴金额
        refundTmTxnOrderDet.setMchntSubsidy(CommonConstant.ZERO_AMOUNT);
        JSONObject relativeDataJsonTrail = new JSONObject();
        //退货订单金额
        relativeDataJsonTrail.put("orderAmt", feeDiscountInfoBean.getMchntSettleAmt());
        //退货商户应收手续费
        relativeDataJsonTrail.put("mchntFeeReceivable", feeDiscountInfoBean.getMchntFeeReceivable());

        //原手续费优惠交易订单金额
        String origOrderAmt = oriRelativeDataJson.get("orderAmt").toString();
        relativeDataJsonTrail.put("origOrderAmt", origOrderAmt);
        //原手续费优惠交易手续费金额
        String origMchntFee = oriRelativeDataJson.get("mchntFeeReceivable").toString();
        relativeDataJsonTrail.put("origMchntFee", origMchntFee);

        //手续费收取方式
        Object feeInputMode = oriRelativeDataJson.get("feeInputMode");
        //商户手续费优惠类型
        String discountType = oriRelativeDataJson.get("discountType").toString();
        //优惠力度
        BigDecimal discount = new BigDecimal(oriRelativeDataJson.get("discount").toString()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);

        //手续费收取方式
        relativeDataJsonTrail.put("feeInputMode", feeInputMode);
        //商户手续费优惠类型
        relativeDataJsonTrail.put("discountType", discountType);
        //优惠力度
        relativeDataJsonTrail.put("discount", discount);

        String relativeData = relativeDataJsonTrail.toString();
        //关联信息
        refundTmTxnOrderDet.setRelativeData(relativeData);
        //订单预留信息
        refundTmTxnOrderDet.setOrderRemark(relativeData);
        //创建人
        refundTmTxnOrderDet.setOprId(CommonConstant.DEFAULT_OPR_ID);
        //创建时间
        refundTmTxnOrderDet.setCreateTime(newTimeStamp);
        //最后修改人
        refundTmTxnOrderDet.setLastOprId("");
        //修改时间
        refundTmTxnOrderDet.setUpdateTime("");
        // 备用字段1
        refundTmTxnOrderDet.setRemark1("");
        // 备用字段2
        refundTmTxnOrderDet.setRemark2("");
        // 备用字段3
        refundTmTxnOrderDet.setRemark3("");
        // 备用字段4
        refundTmTxnOrderDet.setRemark4("");
        // 备用字段5
        refundTmTxnOrderDet.setRemark5("");

        String disTxAmt = tmTxnOrderDetOrig.getDisTxAmt();
        BigDecimal oriDisTxAmt;
        BigDecimal origOrderAmtBigdecimal = new BigDecimal(origOrderAmt);
        BigDecimal mchntFeeDiscount = new BigDecimal(feeDiscountInfoBean.getMchntFeeDiscount());
        if (null != disTxAmt) {
            oriDisTxAmt = new BigDecimal(disTxAmt);
        } else {
            oriDisTxAmt = origOrderAmtBigdecimal;
        }
        //如果原订单金额和优惠交易金额相同，则 原交易不是商户最后一笔非全额优惠，则本笔优惠交易金额和本笔上送的优惠交易金额相同
        if (oriDisTxAmt.compareTo(origOrderAmtBigdecimal) == 0) {
            //如果当前是最后部分退货的最后一笔退款，或者是全额退款，如果本笔交易有手续费优惠，则
            if (mchntFeeDiscount.compareTo(BigDecimal.ZERO) > 0) {
                refundTmTxnOrderDet.setDisTxAmt(feeDiscountInfoBean.getMchntSettleAmt());
            } else {
                //如果没有手续费优惠，则本笔优惠交易金额为0
                refundTmTxnOrderDet.setDisTxAmt(CommonConstant.ZERO_AMOUNT);
            }
        } else {
            //如果不相同，则原交易为此商户最后一笔非全金额手续费优惠,只有当最后一笔退款时登记优惠交易金额，其他时候为0
            if (isLastRefund) {
                refundTmTxnOrderDet.setDisTxAmt(tmTxnOrderDetOrig.getDisTxAmt());
                //使用remark1标识，此订单虽然没有手续费优惠但是需要登记订单明细（有优惠交易金额）
                refundTmTxnOrderDet.setRemark1(CommonConstant.ONE_COMMON_CONSTANT);
            } else {
                refundTmTxnOrderDet.setDisTxAmt(CommonConstant.ZERO_AMOUNT);
            }
        }

        return refundTmTxnOrderDet;
    }

    /**
     * 登记订单明细表——未经试算直接回退的使用
     *
     * @return void
     * @throws Exception 异常信息
     * @author liujinan
     * @date 2020/5/13
     */
    private void recordTxnOrderDetList(List<TMTxnOrderDet> tmTxnOrderDetList) throws Exception {
        TMTxnOrderDetMapper tmTxnOrderDetMapper = new TMTxnOrderDetMapperImpl();
        int returnCodeTmTxnOrderDet = tmTxnOrderDetMapper.insertTMTxnOrderDetList(tmTxnOrderDetList);
        if (Database.DBS_SUCCESS != returnCodeTmTxnOrderDet) {
            rglog.error("插入订单明细数据失败!");
            throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
        }
    }

    /**
     * 登记退款订单流水表
     *
     * @throws Exception 异常信息
     * @author liujinan
     * @date 2020/6/5
     */
    private TMTxnOrder recordTxnOrder(ComboMchntFeeDiscountRefundRequest comboMchntFeeDiscountRefundRequest, TMTxnOrder oriTmTxnOrder, List<PaymentReturnOrderMchntFeeDiscountInfoBean> returnFeeDiscountInfoBeanList) throws Exception {
        String newTimeStamp = new SimpleDateFormat(CommonConstant.TIMESTAMP_FORMAT).format(new Date());

        TMTxnOrder refundTmTxnOrder = new TMTxnOrder();
        //机构编码
        refundTmTxnOrder.setInstId(comboMchntFeeDiscountRefundRequest.getHeader().getInstId());
        //交易日期
        refundTmTxnOrder.setTxnDate(comboMchntFeeDiscountRefundRequest.getHeader().getTransDate());
        //交易时间
        refundTmTxnOrder.setTxnTime(comboMchntFeeDiscountRefundRequest.getHeader().getTransTime());
        //内部交易码
        refundTmTxnOrder.setTxnNum(comboMchntFeeDiscountRefundRequest.getHeader().getTxnNum());
        //业务细分
        refundTmTxnOrder.setBizType(comboMchntFeeDiscountRefundRequest.getHeader().getBizType());
        //业务产品代码
        refundTmTxnOrder.setBizProdCode(oriTmTxnOrder.getBizProdCode());
        //源系统标识
        refundTmTxnOrder.setMsgSrcId(comboMchntFeeDiscountRefundRequest.getHeader().getSrcSysId());
        //前端流水号
        refundTmTxnOrder.setFrontSeqNum(comboMchntFeeDiscountRefundRequest.getHeader().getTraceNo());
        //订单号
        refundTmTxnOrder.setOrderId(comboMchntFeeDiscountRefundRequest.getMchntOrderId());
        //商户编号
        refundTmTxnOrder.setMchntNo(oriTmTxnOrder.getMchntNo());
        //用户编号
        refundTmTxnOrder.setUserId(oriTmTxnOrder.getUserId());

        List<PaymentReturnOrderMchntFeeDiscountInfoBean> feeReturnOrderList = comboMchntFeeDiscountRefundRequest.getFeeReturnOrderList();
        BigDecimal returnAmt = BigDecimal.ZERO;
        for (PaymentReturnOrderMchntFeeDiscountInfoBean paymentReturnOrderMchntFeeDiscountInfoBean : feeReturnOrderList) {
            returnAmt = returnAmt.add(new BigDecimal(paymentReturnOrderMchntFeeDiscountInfoBean.getMchntSettleAmt()));
        }
        //订单金额
        refundTmTxnOrder.setOrderAmt(returnAmt.toString());

        //实际支付金额
        refundTmTxnOrder.setTxnAmt(returnAmt.toString());
        //总补贴金额——总手续费优惠金额
        refundTmTxnOrder.setSubsidyAmt(CommonConstant.ZERO_AMOUNT);
        //机构补贴金额
        refundTmTxnOrder.setBankSubsidyAmt(CommonConstant.ZERO_AMOUNT);
        //商户补贴金额
        refundTmTxnOrder.setMchntSubsidyAmt(CommonConstant.ZERO_AMOUNT);
        //交易状态 1:交易成功
        refundTmTxnOrder.setTransStatus(TransStatusEnum.TRANS_SUCC.getStatus());
        //业务状态 00：业务处理成功
        refundTmTxnOrder.setBizStatus(BizStatusEnum.PROCESS_SUCCESS.getBizStatusCode());
        //批量对账状态 0：未对账
        refundTmTxnOrder.setVerifyStatus(CommonConstant.VERIFY_STATUS_INIT);
        //订单预留信息
        if (!globalTMTxnOrderDetList.isEmpty()) {
            BigDecimal subsidyAmt = BigDecimal.ZERO;
            for (TMTxnOrderDet tmTxnOrderDet : globalTMTxnOrderDetList) {
                subsidyAmt = subsidyAmt.add(new BigDecimal(tmTxnOrderDet.getSubsidy()).abs());
            }
            //订单预留信息  所有的订单的优惠手续费不等于0时，本笔订单流水登记有优惠且参与对账
            if (subsidyAmt.compareTo(BigDecimal.ZERO) > CommonConstant.ZERO) {
                refundTmTxnOrder.setOrderRemark(CommonConstant.DISCOUNT_FLAG_TRUE_CHECK_FLAG_TRUE);
            } else {
                refundTmTxnOrder.setOrderRemark(CommonConstant.DISCOUNT_FLAG_TRUE_CHECK_FLAG_FALSE);
            }
        } else {
            refundTmTxnOrder.setOrderRemark(CommonConstant.DISCOUNT_FLAG_FALSE_CHECK_FLAG_FALSE);
        }
        //原交易日期
        refundTmTxnOrder.setOrigTxnDate(oriTmTxnOrder.getTxnDate());
        //原交易流水号
        refundTmTxnOrder.setOrigSysSeqNum(oriTmTxnOrder.getFrontSeqNum());
        //原交易订单号
        refundTmTxnOrder.setOrigOrderId(oriTmTxnOrder.getOrderId());
        //创建人
        refundTmTxnOrder.setOprId(CommonConstant.DEFAULT_OPR_ID);
        //创建时间
        refundTmTxnOrder.setCreateTime(newTimeStamp);
        //最后修改人
        refundTmTxnOrder.setLastOprId("");
        //修改时间
        refundTmTxnOrder.setUpdateTime("");
        // 备用字段1
        refundTmTxnOrder.setRemark1("");
        // 备用字段2
        refundTmTxnOrder.setRemark2("");
        // 备用字段3
        refundTmTxnOrder.setRemark3("");
        // 备用字段4
        refundTmTxnOrder.setRemark4("");
        // 备用字段5
        refundTmTxnOrder.setRemark5("");

        TMTxnOrderMapper tmTxnOrderMapper = new TMTxnOrderMapperImpl();
        int returnCodeTmTxnOrder = tmTxnOrderMapper.insertSingleRecordIntoTMTxnOrder(refundTmTxnOrder);
        if (Database.DBS_SUCCESS != returnCodeTmTxnOrder) {
            rglog.error("插入订单流水数据失败! INST_ID=<{}>, TRACE_NO=<{}>, ORDER_ID=<{}>, MCHNT_NO=<{}>",
                    refundTmTxnOrder.getInstId(), refundTmTxnOrder.getFrontSeqNum(), refundTmTxnOrder.getOrderId(), refundTmTxnOrder.getMchntNo());
            throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
        }

        return refundTmTxnOrder;
    }

    /**
     * 登记退货统计表  判断当前交易是否在原交易日期的统计周期内，如果在需要更新当前交易的单日统计表    ——未经试算直接回退的使用
     *
     * @return void
     * @throws Exception 异常信息
     * @author liujinan
     * @date 2020/6/4
     */
    private void recordTMStatRefundNoTrail(TMTxnOrder tmTxnOrderOrig, TMTxnOrderDet tmTxnOrderDet) throws Exception {
        String newTimeStamp = new SimpleDateFormat(CommonConstant.TIMESTAMP_FORMAT).format(new Date());

        TMStatRefund tmStatRefund = new TMStatRefund();
        //机构编码
        tmStatRefund.setInstId(tmTxnOrderDet.getInstId());
        //交易日期
        tmStatRefund.setTxnDate(tmTxnOrderOrig.getTxnDate());
        //交易时间
        tmStatRefund.setTxnTime(tmTxnOrderOrig.getTxnTime());
        //系统流水号
        tmStatRefund.setSysSeqNum(tmTxnOrderOrig.getFrontSeqNum());
        //订单号
        tmStatRefund.setOrderId(tmTxnOrderOrig.getOrderId());
        //商户编号
        tmStatRefund.setMchntNo(tmTxnOrderDet.getMchntNo());
        //订单币种
        tmStatRefund.setOrderCcy("CNY");
        //营销活动类型
        tmStatRefund.setMcType(McTypeEnum.MCHNT_FEE_DISCOUNT.getMcTypeCode());
        //交易状态
        tmStatRefund.setTransStatus(TransStatusEnum.TRANS_SUCC.getStatus());
        //业务状态
//        tmStatRefund.setBizStatus(BizStatusEnum.PROCESS_SUCCESS.getBizStatusCode());

        //关联信息
        String relativeDataTrial = tmTxnOrderDet.getRelativeData();
        JSONObject relativeDataJsonTrial = JSONObject.parseObject(relativeDataTrial);
        //商户手续费优惠营销活动编号
        String mchntFeeDiscountMcNo = tmTxnOrderDet.getMcNo();
        //手续费优惠金额
        String mchntFeeDiscount = tmTxnOrderDet.getSubsidy();
        //实收手续费金额
        String mchntFeeActual = new BigDecimal(tmTxnOrderDet.getOriginalAmt()).subtract(new BigDecimal(tmTxnOrderDet.getSubsidy())).toString();

        //原手续费优惠交易订单金额
        String origOrderAmt = relativeDataJsonTrial.get("origOrderAmt").toString();
        //订单金额
        tmStatRefund.setOrderAmt(origOrderAmt);
        //原手续费优惠交易手续费金额
        String origMchntFee = relativeDataJsonTrial.get("origMchntFee").toString();
        //应收/应退商户手续费
        tmStatRefund.setMchntFee(origMchntFee);

        //手续费减免类营销活动编号
        tmStatRefund.setMcNo(mchntFeeDiscountMcNo);
        //手续费减免类规则顺序号
        tmStatRefund.setRuleIndex(tmTxnOrderDet.getRuleIndex());
        //累计退货次数
        tmStatRefund.setRefundCount(CommonConstant.ONE_COMMON_CONSTANT);

        //订单明细金额
        String orderAmt = relativeDataJsonTrial.get("orderAmt").toString();
        //累计退货订单金额
        tmStatRefund.setRefundOrderAmt(orderAmt);
        //累计退货手续费金额
        tmStatRefund.setRefundMchntFee(mchntFeeActual);
        //累计退货优惠金额
        tmStatRefund.setRefundSubsidy(mchntFeeDiscount);
        //累计退货银行优惠金额
        tmStatRefund.setRefundBankSubsidy(mchntFeeDiscount);
        //累计退货商户优惠金额
        tmStatRefund.setRefundMchntSubsidy(BigDecimal.ZERO.toString());
        //创建人
        tmStatRefund.setOprId(CommonConstant.DEFAULT_OPR_ID);
        //创建时间
        tmStatRefund.setCreateTime(newTimeStamp);
        //最后修改人
        tmStatRefund.setLastOprId("");
        //修改时间
        tmStatRefund.setUpdateTime("");
        // 备用字段1
        tmStatRefund.setRemark1("");
        // 备用字段2
        tmStatRefund.setRemark2("");
        // 备用字段3
        tmStatRefund.setRemark3("");
        // 备用字段4
        tmStatRefund.setRemark4("");
        // 备用字段5
        tmStatRefund.setRemark5("");

        //如果是最后一笔退货，更新退货统计表为已全额退款
        if (isLastDeal) {
            tmStatRefund.setBizStatus(BizStatusEnum.PROCESS_REFUNDED.getBizStatusCode());
        } else {
            tmStatRefund.setBizStatus(BizStatusEnum.PROCESS_PARTIALLY_REFUNDED.getBizStatusCode());
        }

        TMStatRefundMapper tmStatRefundMapper = new TMStatRefundMapperImpl();
        int returnCodeTmTxnOrder = tmStatRefundMapper.insertSingleRecordFromTmStatRefund(tmStatRefund);
        if (Database.DBS_SUCCESS != returnCodeTmTxnOrder) {
            rglog.error("登记退货统计表数据失败! INST_ID=<{}>, TRACE_NO=<{}>, ORDER_ID=<{}>, MCHNT_NO=<{}>",
                    tmStatRefund.getInstId(), tmStatRefund.getSysSeqNum(), tmStatRefund.getOrderId(), tmStatRefund.getMchntNo());
            throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
        }

        //判断当前交易是否在原交易日期的统计周期内，如果在需要更新当前交易的单日统计表
        checkDateAndUpdateStatisticalNotrail(tmTxnOrderDet);
    }

    /**
     * 更新退货统计表——未经试算直接回退的使用
     *
     * @return void
     * @throws Exception 异常信息
     * @author liujinan
     * @date 2020/6/4
     */
    private void updateTMStatRefundNoTrail(TMTxnOrder tmTxnOrder, TMTxnOrderDet tmTxnOrderDet, TMStatRefund tmStatRefund) throws Exception {
        String newTimeStamp = new SimpleDateFormat(CommonConstant.TIMESTAMP_FORMAT).format(new Date());
        //关联信息
        String relativeData = tmTxnOrderDet.getRelativeData();
        JSONObject relativeDataJsonThisTime = JSONObject.parseObject(relativeData);
        //手续费优惠金额
        String mchntFeeDiscount = tmTxnOrderDet.getSubsidy();
        //实收手续费金额
        String mchntFeeActual = new BigDecimal(tmTxnOrderDet.getOriginalAmt()).subtract(new BigDecimal(tmTxnOrderDet.getSubsidy())).toString();
        //订单明细金额
        String orderAmt = relativeDataJsonThisTime.get("orderAmt").toString();

        TMStatRefund updateTMStatRefund = new TMStatRefund();
        //机构编码
        updateTMStatRefund.setInstId(tmTxnOrderDet.getInstId());
        //交易日期
        updateTMStatRefund.setTxnDate(tmTxnOrder.getTxnDate());
        //系统流水号
        updateTMStatRefund.setSysSeqNum(tmTxnOrder.getFrontSeqNum());
        //商户编号
        updateTMStatRefund.setMchntNo(tmTxnOrderDet.getMchntNo());

        //累计退货次数  在sql中计算
        updateTMStatRefund.setRefundCount(CommonConstant.ONE_COMMON_CONSTANT);
        //累计退货订单金额  在sql中计算
        updateTMStatRefund.setRefundOrderAmt(orderAmt);
        //累计退货手续费金额  在sql中计算
        updateTMStatRefund.setRefundMchntFee(mchntFeeActual);
        //累计退货优惠金额  在sql中计算
        updateTMStatRefund.setRefundSubsidy(mchntFeeDiscount);
        //累计退货银行优惠金额  在sql中计算
        updateTMStatRefund.setRefundBankSubsidy(mchntFeeDiscount);
        //累计退货商户优惠金额  在sql中计算
        updateTMStatRefund.setRefundMchntSubsidy(CommonConstant.ZERO_AMOUNT);
        //修改时间
        updateTMStatRefund.setUpdateTime(newTimeStamp);

        //如果是最后一笔退货，更新退货统计表为已全额退款
        if (isLastDeal) {
            updateTMStatRefund.setBizStatus(BizStatusEnum.PROCESS_REFUNDED.getBizStatusCode());
        } else {
            updateTMStatRefund.setBizStatus(BizStatusEnum.PROCESS_PARTIALLY_REFUNDED.getBizStatusCode());
        }

        TMStatRefundMapper tmStatRefundMapper = new TMStatRefundMapperImpl();
        int returnCodeTmTxnOrder = tmStatRefundMapper.updateSingleRecordFromTmStatRefund(updateTMStatRefund);
        if (Database.DBS_SUCCESS != returnCodeTmTxnOrder) {
            rglog.error("更新退货统计表数据失败! INST_ID=<{}>, TRACE_NO=<{}>, ORDER_ID=<{}>, MCHNT_NO=<{}>",
                    updateTMStatRefund.getInstId(), updateTMStatRefund.getSysSeqNum(), updateTMStatRefund.getOrderId(), updateTMStatRefund.getMchntNo());
            throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
        }

        //判断当前交易是否在原交易日期的统计周期内，如果在需要更新当前交易的单日统计表
        checkDateAndUpdateStatisticalNotrail(tmTxnOrderDet);
    }

    /**
     * 更新原手续费优惠订单明细——未经试算直接回退的使用
     *
     * @return void
     * @throws Exception 异常信息
     * @author liujinan
     * @date 2020/6/4
     */
    private void updateTMTxnOrderDetNotrail(TMTxnOrder tmTxnOrderOrig, TMTxnOrderDet tmTxnOrderDetOrig, TMStatRefund tmStatRefund, String refundOrderAmt) throws Exception {
        String newTimeStamp = new SimpleDateFormat(CommonConstant.TIMESTAMP_FORMAT).format(new Date());

        //关联信息
        String relativeData = tmTxnOrderDetOrig.getRelativeData();
        JSONObject relativeDataJson = JSONObject.parseObject(relativeData);
        //原订单明细订单总金额
        String orderAmt = relativeDataJson.get("orderAmt").toString();

        TMTxnOrderDet tmTxnOrderDet = new TMTxnOrderDet();
        //本订单明细已经退货订单金额
        BigDecimal alredayRefundAmt = BigDecimal.ZERO;

        if (null != tmStatRefund) {
            //本订单明细已经退货订单金额
            alredayRefundAmt = new BigDecimal(tmStatRefund.getRefundOrderAmt());
        }
        //已退款小于订单总金额，如果不小于应该是等于，不可能大于
        if ((alredayRefundAmt.add(new BigDecimal(refundOrderAmt))).compareTo(new BigDecimal(orderAmt)) < 0) {
            //设置手续费优惠业务状态为部分退款
            tmTxnOrderDet.setBizStatus(BizStatusEnum.PROCESS_PARTIALLY_REFUNDED.getBizStatusCode());
            //设置本笔交易不是最后一笔退款
            isLastDeal = false;
        } else {
            //设置手续费优惠业务状态为全额退款
            tmTxnOrderDet.setBizStatus(BizStatusEnum.PROCESS_REFUNDED.getBizStatusCode());
            //设置本笔交易是最后一笔退款
            isLastDeal = true;
        }

        TMTxnOrderDetMapper TmTxnOrderDetMapper = new TMTxnOrderDetMapperImpl();

        //机构编码
        tmTxnOrderDet.setInstId(tmTxnOrderOrig.getInstId());
        //交易日期
        tmTxnOrderDet.setTxnDate(tmTxnOrderOrig.getTxnDate());
        //前端流水号
        tmTxnOrderDet.setFrontSeqNum(tmTxnOrderOrig.getFrontSeqNum());
        //商户编号
        tmTxnOrderDet.setMchntNo(tmTxnOrderDetOrig.getMchntNo());
        //营销活动编号
        tmTxnOrderDet.setMcNo(tmTxnOrderDetOrig.getMcNo());
        //更新时间
        tmTxnOrderDet.setUpdateTime(newTimeStamp);

        //更新手续费优惠订单明细
        int updateTmTxnOrderDetCode = TmTxnOrderDetMapper.updateTmTxnOrderDetByKey(tmTxnOrderDet);
        if (Database.DBS_SUCCESS != updateTmTxnOrderDetCode) {
            rglog.error("更新手续费优惠订单明细表数据失败! INST_ID=<{}>, TRACE_NO=<{}>, ORDER_ID=<{}>, MCHNT_NO=<{}>",
                    tmTxnOrderDet.getInstId(), tmTxnOrderDet.getFrontSeqNum(), tmTxnOrderDet.getOrderId(), tmTxnOrderDet.getMchntNo());
            throw new BizException(RespCodeEnum.FAILED_UPDATE_T_M_TXN_ORDER_DET.getRespCode(), RespCodeEnum.FAILED_UPDATE_T_M_TXN_ORDER_DET.getRespDesc());
        }
    }

    /**
     * 更新原手续费优惠订单流水——未经试算直接回退的使用
     *
     * @return void
     * @throws Exception 异常信息
     * @author liujinan
     * @date 2020/5/14
     */
    private void updateTMTxnOrderNoTrail(TMTxnOrder tmTxnOrderOrig, TMTxnOrder tmTxnOrderthisTime) throws Exception {
        String newTimeStamp = new SimpleDateFormat(CommonConstant.TIMESTAMP_FORMAT).format(new Date());

        Boolean isOrderFullRefund = true;
        /* 查询原交易订单明细信息 */
        List<TMTxnOrderDet> tmTxnOrderDetList = getOriginalTransactionOrderDetailInfo(globalInstId, tmTxnOrderOrig.getTxnDate(), tmTxnOrderOrig.getFrontSeqNum());
        if (null == tmTxnOrderDetList || tmTxnOrderDetList.isEmpty()) {
            rglog.error("机构<{}>在<{}>的原交易订单明细信息<{}>失败!", globalInstId, tmTxnOrderOrig.getTxnDate(), tmTxnOrderOrig.getFrontSeqNum());
            throw new BizException(RespCodeEnum.FAILED_TO_CHECK_ORIGINAL_TXNDET_INFO_ERROR.getRespCode(), RespCodeEnum.FAILED_TO_CHECK_ORIGINAL_TXNDET_INFO_ERROR.getRespDesc());
        }
        //循环遍历原订单流水对应的订单明细信息，如果状态都为已全额退款，则更新原交易流水为已全额退款，否则为部分退款
        for (TMTxnOrderDet tMTxnOrderDet : tmTxnOrderDetList) {
            if (!BizStatusEnum.PROCESS_REFUNDED.getBizStatusCode().equals(tMTxnOrderDet.getBizStatus())) {
                isOrderFullRefund = false;
                break;
            }
        }
        if (isOrderFullRefund) {
            /* 全额退款,报文内容和原支付交易内容相同 */
            tmTxnOrderOrig.setBizStatus(BizStatusEnum.PROCESS_REFUNDED.getBizStatusCode());
        } else {
            /* 部分退款,优惠部分为0,其他和退货金额相同 */
            tmTxnOrderOrig.setBizStatus(BizStatusEnum.PROCESS_PARTIALLY_REFUNDED.getBizStatusCode());
        }

        tmTxnOrderOrig.setUpdateTime(newTimeStamp);

        //更新手续费优惠订单流水
        int updateTxnOrderBizStatusReturnCode = updateTxnOrderBizStatusInfo(tmTxnOrderOrig);
        if (CommonConstant.PROCESS_SUCCESS != updateTxnOrderBizStatusReturnCode) {
            rglog.error("更新订单流水表失败,流水号<{}>!", tmTxnOrderOrig.getFrontSeqNum());
            throw new BizException(RespCodeEnum.FAILED_UPDATE_T_M_TXN_ORDER.getRespCode(), RespCodeEnum.FAILED_UPDATE_T_M_TXN_ORDER.getRespDesc());
        }
    }

    /**
     * 请求报文检查
     *
     * @param comboMchntFeeDiscountRefundRequest
     * @throws BizException 异常信息
     * @author liujinan
     * @date 2020/6/11
     */
    private void checkRequestMessage(ComboMchntFeeDiscountRefundRequest comboMchntFeeDiscountRefundRequest) throws BizException {

        globalTMTxnOrderDetList = new ArrayList<>();

        if (StringUtil.isNullorEmpty(comboMchntFeeDiscountRefundRequest.getHeader().getInstId())) {
            rglog.error("法人机构号必须上送!");
            throw new BizException(RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespCode(), RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespDesc());
        } else {
            globalInstId = comboMchntFeeDiscountRefundRequest.getHeader().getInstId();
        }

        if (StringUtil.isNullorEmpty(comboMchntFeeDiscountRefundRequest.getHeader().getTransDate())) {
            rglog.error("交易日期必须上送!");
            throw new BizException(RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespCode(), RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespDesc());
        } else {
            globalTxnDate = comboMchntFeeDiscountRefundRequest.getHeader().getTransDate();
        }

        if (StringUtil.isNullorEmpty(comboMchntFeeDiscountRefundRequest.getOrigTxnDate())) {
            rglog.error("原交易日期为空,需要上送原交易日期 !");
            throw new BizException(RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespCode(), RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespDesc());
        }

        if (StringUtil.isNullorEmpty(comboMchntFeeDiscountRefundRequest.getOrigTraceNo())) {
            rglog.error("原交易流水号为空,需要上送原交易流水号!");
            throw new BizException(RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespCode(), RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespDesc());
        }

        if (StringUtil.isNullorEmpty(comboMchntFeeDiscountRefundRequest.getMchntOrderId())) {
            rglog.error("商户订单号为空,需要上送商户订单号!");
            throw new BizException(RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespCode(), RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespDesc());
        }

        if (StringUtil.isNullorEmpty(comboMchntFeeDiscountRefundRequest.getOrigTrialTxnDate()) || StringUtil.isNullorEmpty(comboMchntFeeDiscountRefundRequest.getOrigTrialTraceNo())) {
            if (null == comboMchntFeeDiscountRefundRequest.getFeeReturnOrderList() || comboMchntFeeDiscountRefundRequest.getFeeReturnOrderList().isEmpty()) {
                rglog.error("原试算订单流水或日期为空,未经试算的回退!需上送手续费减免明细信息");
                throw new BizException(RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespCode(), RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespDesc());
            }
        }
    }

    /**
     * 判断是否在支付统计周期内，并更新各单日统计表
     *
     * @param tmTxnOrderDet
     * @throws BizException 异常信息
     * @author liujinan
     * @date 2020/7/25
     */
    private void checkDateAndUpdateStatistical(TMTxnOrderDet tmTxnOrderDet, TMTxnOrderDet tmTxnOrderDetTrial) throws Exception {

        String instId = tmTxnOrderDet.getInstId();
        String mcNo = tmTxnOrderDet.getMcNo();
        String ruleIndex = tmTxnOrderDet.getRuleIndex();
        String txnDate = globalTxnDate;
        String mchntNo = tmTxnOrderDet.getMchntNo();

        MchntInfoMapper mchntInfoMapper = new MchntInfoMapperImpl();
        TBMchntBaseInfo mchntBaseInfo = mchntInfoMapper.selectMompMchntBaseInfoByPrimaryKey(instId, mchntNo);
        if (null == mchntBaseInfo) {
            //查询不到商户信息，流程结束
            rglog.error("查询商户基本信息信息失败, INST_ID=<{}>, MCHNT_NO=<{}>", instId, mchntNo);
            throw new BizException(RespCodeEnum.GET_MCHNT_BASE_INFO_ERROR.getRespCode(), RespCodeEnum.GET_MCHNT_BASE_INFO_ERROR.getRespDesc());
        }
        //商户性质
        String mchntType = mchntBaseInfo.getMchntType();
        //独立营销活动标识
        String idpdCmavyFlg = mchntBaseInfo.getMarketFlag();
        //连锁商户号
        String chainMchntNo = mchntBaseInfo.getChainMchntNo();
        //是否独立维护商户资料
        String independentDataFlag = mchntBaseInfo.getIndependentDataFlag();
        if (CommonConstant.YES.equals(independentDataFlag) && MchntTypeEnum.CHAIN_MCHNT_STORE.getMchntType().equals(mchntType) && CommonConstant.ZERO_COMMON_CONSTANT.equals(idpdCmavyFlg)) {
            rglog.info("商户<{}> 商户类型为11:连锁商户门店，商户独立营销活动标识为<{}> 是否独立维护商户资料<{}> 原正向交易计算营销时根据上级商户<{}> 获取营销活动计算的!", mchntNo, idpdCmavyFlg, independentDataFlag, chainMchntNo);
            mchntNo = chainMchntNo;
        } else {
            rglog.info("商户<{}> 是否独立维护商户资料<{}> 商户类型为<{}> 原正向交易无需判断独立营销活动标识，均使用当前商户号计算的营销！", mchntBaseInfo.getMchntNo(), independentDataFlag, idpdCmavyFlg);
        }

        int limitFlag;
        TMStatMfdCriteriaMapper tmStatMfdCriteriaMapper = new TMStatMfdCriteriaMapperImpl();
        TMStatMfdCriteria tmStatMfdCriteria = tmStatMfdCriteriaMapper.selectTMStatMfdCriteriaByUsingMchntNoAndMcNoAndDateRange(tmTxnOrderDet.getInstId(), mchntNo, tmTxnOrderDet.getTxnDate(), mcNo);
        if (null == tmStatMfdCriteria) {
            /* 未取到数据,说明当前退货日期已超过原支付交易商户统计周期,不回退额度 */
            rglog.info("当前退货交易日期<{}> 未取到原支付交易在<{}>的流水号<{}>订单号<{}>的达标统计表数据,不回退统计周期数据!", globalTxnDate, tmTxnOrderDet.getTxnDate(), tmTxnOrderDet.getFrontSeqNum(), tmTxnOrderDet.getOrderId());
            limitFlag = CommonConstant.FLAG_NOT_SET;
        } else {
            /* 判断当前退货交易日期是否在原支付交易商户统计周期内 */
            if (CommonConstant.ZERO == MompDateUtil.checkDateRange(globalTxnDate, tmStatMfdCriteria.getPeriodStartDate(), tmStatMfdCriteria.getPeriodEndDate())) {
                rglog.info("当前退货交易日期<{}>未超出原支付交易在<{}>的流水号<{}>的统计周期,继续判断退货时是否到达优惠额度限制!", globalTxnDate, tmTxnOrderDet.getTxnDate(), tmTxnOrderDet.getFrontSeqNum());
                McMchntFeeDiscountTransData mcMchntFeeDiscountTransData = new McMchntFeeDiscountTransData();
                Boolean isReachRuleOrMchntLimit;
                //交易规则为0，则为新商户免手续费的，具体规则号的则为存量商户的
                if (CommonConstant.ZERO_COMMON_CONSTANT.equals(ruleIndex)) {
                    //获取新商户当前各维度统计数据值
                    fetchNewMchntFeeDiscountMcQuotaData(mcMchntFeeDiscountTransData, tmStatMfdCriteria);
                    //判断各维度是否达到上限
                    isReachRuleOrMchntLimit = judgeNewMchntIsReachLimit(mcMchntFeeDiscountTransData, tmStatMfdCriteria);
                } else {
                    //获取当前各维度统计数据值
                    fetchAllMchntFeeDiscountMcQuotaData(mcMchntFeeDiscountTransData, tmStatMfdCriteria);
                    //判断各维度是否达到上限
                    isReachRuleOrMchntLimit = judgeIsReachRuleOrMchntLimit(mcMchntFeeDiscountTransData, tmStatMfdCriteria);
                }
                if (isReachRuleOrMchntLimit) {
                    rglog.info("累计交易额度未达到上限值,需要回退统计周期数据!");
                    limitFlag = CommonConstant.FLAG_SET;
                } else {
                    rglog.info("累计交易额度已达到上限值,不需要回退统计周期数据!");
                    limitFlag = CommonConstant.FLAG_NOT_SET;
                }
            } else {
                rglog.info("当前退货交易日期<{}>已超出原支付交易在<{}>的流水号<{}>订单号<{}>的统计周期,不回退统计周期数据!", globalTxnDate, tmTxnOrderDet.getTxnDate(), tmTxnOrderDet.getFrontSeqNum(), tmTxnOrderDet.getOrderId());
                limitFlag = CommonConstant.FLAG_NOT_SET;
            }
        }

        /*当前退货时间在消费交易的统计周期内,需调整额度 */
        if (CommonConstant.FLAG_SET == limitFlag) {
            //关联信息
            String relativeData = tmTxnOrderDetTrial.getRelativeData();
            JSONObject relativeDataJson = JSONObject.parseObject(relativeData);

            //获取回退试算明细中的订单金额（商户清算金额）
            String orderAmtString = relativeDataJson.get("orderAmt").toString();
            BigDecimal orderAmt = new BigDecimal(orderAmtString).multiply(new BigDecimal(CommonConstant.MINUS_ONE)).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
            //获取回退试算明细中总补贴金额
            BigDecimal totalSubsidyString = new BigDecimal(tmTxnOrderDetTrial.getSubsidy()).multiply(new BigDecimal(CommonConstant.MINUS_ONE)).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);

            TMStatMfdDay tmStatMfdDay1 = new TMStatMfdDay();
            tmStatMfdDay1.setInstId(instId);
            tmStatMfdDay1.setTxnDate(txnDate);
            tmStatMfdDay1.setMcNo(mcNo);
            tmStatMfdDay1.setRuleIndex(ruleIndex);
            //本笔交易是最后一笔退款，则更新统计表中的累计笔数
            if (isLastDeal) {
                tmStatMfdDay1.setTotalQtyAcc(CommonConstant.MINUS_ONE_COMMON_CONSTANT);
                tmStatMfdDay1.setTxnQtyAcc(CommonConstant.MINUS_ONE_COMMON_CONSTANT);
            } else {
                tmStatMfdDay1.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                tmStatMfdDay1.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            }
            tmStatMfdDay1.setTotalAmtAcc(totalSubsidyString.toString());
            tmStatMfdDay1.setTxnAmtAcc(orderAmt.toString());
            tmStatMfdDay1.setMchntQty(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdDay1.setMchntOldQualified(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdDay1.setMchntNewQualified(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdDay1.setMchntExitQty(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdDay1.setAvgAmt(CommonConstant.ZERO_AMOUNT);
            tmStatMfdDay1.setPaidAmt(CommonConstant.ZERO_AMOUNT);
            tmStatMfdDay1.setOprId(CommonConstant.DEFAULT_OPR_ID);
            tmStatMfdDay1.setCreateTime(globalTimeStamp);
            tmStatMfdDay1.setLastOprId(CommonConstant.DEFAULT_OPR_ID);
            tmStatMfdDay1.setUpdateTime(globalTimeStamp);

            rglog.info("机构<{}> 营销活动<{}> 规则<{}> 更新手续费减免活动单日统计表...", tmStatMfdDay1.getInstId(), tmStatMfdDay1.getMcNo(), tmStatMfdDay1.getRuleIndex());
            /* 手续费减免活动单日统计表 */
            TMStatMfdDayMapper tmStatMfdDayMapper = new TMStatMfdDayMapperImpl();
            int returnCode = tmStatMfdDayMapper.updateMchntFeeDiscountDayStatistics(tmStatMfdDay1);
            if (CommonConstant.PROCESS_SUCCESS != returnCode) {
                if (cc.rengu.utility.dbs.Database.DBS_NOT_FOUND == returnCode) {
                    int returnCode2 = tmStatMfdDayMapper.insertTMStatMfdDay(tmStatMfdDay1);
                    if (CommonConstant.PROCESS_SUCCESS != returnCode2) {
                        /* 插入数据失败 */
                        rglog.error("插入法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStatMfdDay1.getInstId(), tmStatMfdDay1.getMcNo(), tmStatMfdDay1.getRuleIndex(), returnCode);
                        throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
                    }
                } else {
                    /* 更新数据失败 */
                    rglog.error("更新法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStatMfdDay1.getInstId(), tmStatMfdDay1.getMcNo(), tmStatMfdDay1.getRuleIndex(), returnCode);
                    throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
                }
            }

            //如果当规则不是0 ，则还需要更新规则为0的记录
            if (!CommonConstant.ZERO_COMMON_CONSTANT.equals(tmStatMfdDay1.getRuleIndex())) {
                tmStatMfdDay1.setRuleIndex(CommonConstant.ZERO_COMMON_CONSTANT);

                returnCode = tmStatMfdDayMapper.updateMchntFeeDiscountDayStatistics(tmStatMfdDay1);
                if (CommonConstant.PROCESS_SUCCESS != returnCode) {
                    if (cc.rengu.utility.dbs.Database.DBS_NOT_FOUND == returnCode) {
                        int returnCode2 = tmStatMfdDayMapper.insertTMStatMfdDay(tmStatMfdDay1);
                        if (CommonConstant.PROCESS_SUCCESS != returnCode2) {
                            /* 插入数据失败 */
                            rglog.error("插入法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStatMfdDay1.getInstId(), tmStatMfdDay1.getMcNo(), tmStatMfdDay1.getRuleIndex(), returnCode);
                            throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
                        }
                    } else {
                        /* 更新数据失败 */
                        rglog.error("更新法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStatMfdDay1.getInstId(), tmStatMfdDay1.getMcNo(), tmStatMfdDay1.getRuleIndex(), returnCode);
                        throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
                    }
                }
            }

            /* 手续费减免活动商户单日统计表 */
            TMStatMfdMchntDay tmStatMfdMchntDay1 = new TMStatMfdMchntDay();
            tmStatMfdMchntDay1.setInstId(instId);
            tmStatMfdMchntDay1.setTxnDate(globalTxnDate);
            tmStatMfdMchntDay1.setMcNo(mcNo);
            tmStatMfdMchntDay1.setMchntNo(mchntNo);
            tmStatMfdMchntDay1.setRuleIndex(ruleIndex);
            //本笔交易是最后一笔退款，则更新统计表中的累计笔数
            if (isLastDeal) {
                tmStatMfdMchntDay1.setTotalQtyAcc(CommonConstant.MINUS_ONE_COMMON_CONSTANT);
                tmStatMfdMchntDay1.setTxnQtyAcc(CommonConstant.MINUS_ONE_COMMON_CONSTANT);
            } else {
                tmStatMfdMchntDay1.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                tmStatMfdMchntDay1.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            }
            tmStatMfdMchntDay1.setTotalAmtAcc(totalSubsidyString.toString());
            tmStatMfdMchntDay1.setTxnAmtAcc(orderAmt.toString());
            tmStatMfdMchntDay1.setTotalAvgAmt(CommonConstant.ZERO_AMOUNT);
            tmStatMfdMchntDay1.setExitStatus(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchntDay1.setCashbackStatus(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchntDay1.setCashbackAmt(CommonConstant.ZERO_AMOUNT);
            tmStatMfdMchntDay1.setOprId(CommonConstant.DEFAULT_OPR_ID);
            tmStatMfdMchntDay1.setCreateTime(globalTimeStamp);
            tmStatMfdMchntDay1.setLastOprId(CommonConstant.DEFAULT_OPR_ID);
            tmStatMfdMchntDay1.setUpdateTime(globalTimeStamp);

            //设置规则编号为0的需要更新，即使本条本来就是为0的也不影响
            tmStatMfdMchntDay1.setRemark1(CommonConstant.ZERO_COMMON_CONSTANT);

            rglog.info("机构<{}> 营销活动<{}> 规则<{}> 更新手续费减免活动商户单日统计表...", tmStatMfdMchntDay1.getInstId(), tmStatMfdMchntDay1.getMcNo(), tmStatMfdMchntDay1.getRuleIndex());
            /* 手续费减免活动商户单日统计表 */
            TMStatMfdMchntDayMapper tmStatMfdMchntDayMapper = new TMStatMfdMchntDayMapperImpl();
            int returnCode2 = tmStatMfdMchntDayMapper.updateMchntFeeDiscountMchntDayStatistics(tmStatMfdMchntDay1);
            if (CommonConstant.PROCESS_SUCCESS != returnCode2) {
                if (cc.rengu.utility.dbs.Database.DBS_NOT_FOUND == returnCode) {
                    int returnCode3 = tmStatMfdMchntDayMapper.insertMchntFeeDiscountMchntDayStatistics(tmStatMfdMchntDay1);
                    if (CommonConstant.PROCESS_SUCCESS != returnCode3) {
                        /* 插入数据失败 */
                        rglog.error("插入法人机构<{}> 营销活动<{}> 规则<{}> 更新手续费减免活动商户单日统计表数据失败! RETURN_CODE=<{}>", tmStatMfdDay1.getInstId(), tmStatMfdDay1.getMcNo(), tmStatMfdDay1.getRuleIndex(), returnCode);
                        throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
                    }
                } else {
                    /* 更新数据失败 */
                    rglog.error("更新法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStatMfdMchntDay1.getInstId(), tmStatMfdMchntDay1.getMcNo(), tmStatMfdMchntDay1.getRuleIndex(), returnCode);
                    throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
                }
            }

            //如果当规则不是0 ，则还需要更新规则为0的记录
            if (!CommonConstant.ZERO_COMMON_CONSTANT.equals(tmStatMfdMchntDay1.getRuleIndex())) {
                tmStatMfdMchntDay1.setRuleIndex(CommonConstant.ZERO_COMMON_CONSTANT);

                returnCode2 = tmStatMfdMchntDayMapper.updateMchntFeeDiscountMchntDayStatistics(tmStatMfdMchntDay1);
                if (CommonConstant.PROCESS_SUCCESS != returnCode2) {
                    if (cc.rengu.utility.dbs.Database.DBS_NOT_FOUND == returnCode) {
                        int returnCode3 = tmStatMfdMchntDayMapper.insertMchntFeeDiscountMchntDayStatistics(tmStatMfdMchntDay1);
                        if (CommonConstant.PROCESS_SUCCESS != returnCode3) {
                            /* 插入数据失败 */
                            rglog.error("插入法人机构<{}> 营销活动<{}> 规则<{}> 更新手续费减免活动商户单日统计表数据失败! RETURN_CODE=<{}>", tmStatMfdDay1.getInstId(), tmStatMfdDay1.getMcNo(), tmStatMfdDay1.getRuleIndex(), returnCode);
                            throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
                        }
                    } else {
                        /* 更新数据失败 */
                        rglog.error("更新法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStatMfdMchntDay1.getInstId(), tmStatMfdMchntDay1.getMcNo(), tmStatMfdMchntDay1.getRuleIndex(), returnCode);
                        throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
                    }
                }
            }
        }
    }

    /**
     * 判断是否在支付统计周期内，并更新各单日统计表
     *
     * @param tmTxnOrderDet
     * @throws BizException 异常信息
     * @author liujinan
     * @date 2020/9/21
     */
    private void checkDateAndUpdateStatisticalNotrail(TMTxnOrderDet tmTxnOrderDet) throws Exception {

        String instId = tmTxnOrderDet.getInstId();
        String mcNo = tmTxnOrderDet.getMcNo();
        String ruleIndex = tmTxnOrderDet.getRuleIndex();
        String txnDate = globalTxnDate;
        String mchntNo = tmTxnOrderDet.getMchntNo();

        MchntInfoMapper mchntInfoMapper = new MchntInfoMapperImpl();
        TBMchntBaseInfo mchntBaseInfo = mchntInfoMapper.selectMompMchntBaseInfoByPrimaryKey(instId, mchntNo);
        if (null == mchntBaseInfo) {
            //查询不到商户信息，流程结束
            rglog.error("查询商户基本信息信息失败, INST_ID=<{}>, MCHNT_NO=<{}>", instId, mchntNo);
            throw new BizException(RespCodeEnum.GET_MCHNT_BASE_INFO_ERROR.getRespCode(), RespCodeEnum.GET_MCHNT_BASE_INFO_ERROR.getRespDesc());
        }
        //商户性质
        String mchntType = mchntBaseInfo.getMchntType();
        //独立营销活动标识
        String idpdCmavyFlg = mchntBaseInfo.getMarketFlag();
        //连锁商户号
        String chainMchntNo = mchntBaseInfo.getChainMchntNo();
        //是否独立维护商户资料
        String independentDataFlag = mchntBaseInfo.getIndependentDataFlag();
        if (CommonConstant.YES.equals(independentDataFlag) && MchntTypeEnum.CHAIN_MCHNT_STORE.getMchntType().equals(mchntType) && CommonConstant.ZERO_COMMON_CONSTANT.equals(idpdCmavyFlg)) {
            rglog.info("商户<{}> 商户类型为11:连锁商户门店，商户独立营销活动标识为<{}> 是否独立维护商户资料<{}> 原正向交易计算营销时根据上级商户<{}> 获取营销活动计算的!", mchntNo, idpdCmavyFlg, independentDataFlag, chainMchntNo);
            mchntNo = chainMchntNo;
        } else {
            rglog.info("商户<{}> 是否独立维护商户资料<{}> 商户类型为<{}> 原正向交易无需判断独立营销活动标识，均使用当前商户号计算的营销！", mchntBaseInfo.getMchntNo(), independentDataFlag, mchntType);
        }

        int limitFlag;
        TMStatMfdCriteriaMapper tmStatMfdCriteriaMapper = new TMStatMfdCriteriaMapperImpl();
        TMStatMfdCriteria tmStatMfdCriteria = tmStatMfdCriteriaMapper.selectTMStatMfdCriteriaByUsingMchntNoAndMcNoAndDateRange(tmTxnOrderDet.getInstId(), mchntNo, tmTxnOrderDet.getTxnDate(), mcNo);
        if (null == tmStatMfdCriteria) {
            /* 未取到数据,说明当前退货日期已超过原支付交易商户统计周期,不回退额度 */
            rglog.info("当前退货交易日期<{}> 未取到原支付交易在<{}>的流水号<{}>订单号<{}>的达标统计表数据,不回退统计周期数据!", globalTxnDate, tmTxnOrderDet.getTxnDate(), tmTxnOrderDet.getFrontSeqNum(), tmTxnOrderDet.getOrderId());
            limitFlag = CommonConstant.FLAG_NOT_SET;
        } else {
            /* 判断当前退货交易日期是否在原支付交易商户统计周期内 */
            if (CommonConstant.ZERO == MompDateUtil.checkDateRange(globalTxnDate, tmStatMfdCriteria.getPeriodStartDate(), tmStatMfdCriteria.getPeriodEndDate())) {
                rglog.info("当前退货交易日期<{}>未超出原支付交易在<{}>的流水号<{}>订单号<{}>的统计周期,继续判断退货时是否到达优惠额度限制!", globalTxnDate, tmTxnOrderDet.getTxnDate(), tmTxnOrderDet.getFrontSeqNum(), tmTxnOrderDet.getOrderId());
                McMchntFeeDiscountTransData mcMchntFeeDiscountTransData = new McMchntFeeDiscountTransData();
                Boolean isReachRuleOrMchntLimit;
                //交易规则为0，则为新商户免手续费的，具体规则号的则为存量商户的
                if (CommonConstant.ZERO_COMMON_CONSTANT.equals(ruleIndex)) {
                    //获取新商户当前各维度统计数据值
                    fetchNewMchntFeeDiscountMcQuotaData(mcMchntFeeDiscountTransData, tmStatMfdCriteria);
                    //判断各维度是否达到上限
                    isReachRuleOrMchntLimit = judgeNewMchntIsReachLimit(mcMchntFeeDiscountTransData, tmStatMfdCriteria);
                } else {
                    //获取当前各维度统计数据值
                    fetchAllMchntFeeDiscountMcQuotaData(mcMchntFeeDiscountTransData, tmStatMfdCriteria);
                    //判断各维度是否达到上限
                    isReachRuleOrMchntLimit = judgeIsReachRuleOrMchntLimit(mcMchntFeeDiscountTransData, tmStatMfdCriteria);
                }
                if (isReachRuleOrMchntLimit) {
                    rglog.info("累计交易额度未达到上限值,需要回退统计周期数据!");
                    limitFlag = CommonConstant.FLAG_SET;
                } else {
                    rglog.info("累计交易额度已达到上限值,不需要回退统计周期数据!");
                    limitFlag = CommonConstant.FLAG_NOT_SET;
                }
            } else {
                rglog.info("当前退货交易日期<{}>已超出原支付交易在<{}>的流水号<{}>订单号<{}>的统计周期,不回退统计周期数据!", globalTxnDate, tmTxnOrderDet.getTxnDate(), tmTxnOrderDet.getFrontSeqNum(), tmTxnOrderDet.getOrderId());
                limitFlag = CommonConstant.FLAG_NOT_SET;
            }
        }

        /*当前退货时间在消费交易的统计周期内,需调整额度 */
        if (CommonConstant.FLAG_SET == limitFlag) {
            //关联信息
            String relativeData = tmTxnOrderDet.getRelativeData();
            JSONObject relativeDataJson = JSONObject.parseObject(relativeData);

            //获取明细中的订单金额（商户清算金额）
            String orderAmtString = relativeDataJson.get("orderAmt").toString();
            BigDecimal orderAmt = new BigDecimal(tmTxnOrderDet.getDisTxAmt()).multiply(new BigDecimal(CommonConstant.MINUS_ONE)).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
            //获取回退试算明细中总补贴金额
            BigDecimal totalSubsidyString = new BigDecimal(tmTxnOrderDet.getSubsidy()).multiply(new BigDecimal(CommonConstant.MINUS_ONE)).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);

            TMStatMfdDay tmStatMfdDay1 = new TMStatMfdDay();
            tmStatMfdDay1.setInstId(instId);
            tmStatMfdDay1.setTxnDate(txnDate);
            tmStatMfdDay1.setMcNo(mcNo);
            tmStatMfdDay1.setRuleIndex(ruleIndex);
            //本笔交易是最后一笔退款，则更新统计表中的累计笔数
            if (isLastDeal) {
                tmStatMfdDay1.setTotalQtyAcc(CommonConstant.MINUS_ONE_COMMON_CONSTANT);
                tmStatMfdDay1.setTxnQtyAcc(CommonConstant.MINUS_ONE_COMMON_CONSTANT);
            } else {
                tmStatMfdDay1.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                tmStatMfdDay1.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            }
            tmStatMfdDay1.setTotalAmtAcc(totalSubsidyString.toString());
            tmStatMfdDay1.setTxnAmtAcc(orderAmt.toString());
            tmStatMfdDay1.setMchntQty(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdDay1.setMchntOldQualified(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdDay1.setMchntNewQualified(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdDay1.setMchntExitQty(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdDay1.setAvgAmt(CommonConstant.ZERO_AMOUNT);
            tmStatMfdDay1.setPaidAmt(CommonConstant.ZERO_AMOUNT);
            tmStatMfdDay1.setOprId(CommonConstant.DEFAULT_OPR_ID);
            tmStatMfdDay1.setCreateTime(globalTimeStamp);
            tmStatMfdDay1.setLastOprId(CommonConstant.DEFAULT_OPR_ID);
            tmStatMfdDay1.setUpdateTime(globalTimeStamp);

            rglog.info("机构<{}> 营销活动<{}> 规则<{}> 更新手续费减免活动单日统计表...", tmStatMfdDay1.getInstId(), tmStatMfdDay1.getMcNo(), tmStatMfdDay1.getRuleIndex());
            /* 手续费减免活动单日统计表 */
            TMStatMfdDayMapper tmStatMfdDayMapper = new TMStatMfdDayMapperImpl();
            int returnCode = tmStatMfdDayMapper.updateMchntFeeDiscountDayStatistics(tmStatMfdDay1);
            if (CommonConstant.PROCESS_SUCCESS != returnCode) {
                if (cc.rengu.utility.dbs.Database.DBS_NOT_FOUND == returnCode) {
                    int returnCode2 = tmStatMfdDayMapper.insertTMStatMfdDay(tmStatMfdDay1);
                    if (CommonConstant.PROCESS_SUCCESS != returnCode2) {
                        /* 插入数据失败 */
                        rglog.error("插入法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStatMfdDay1.getInstId(), tmStatMfdDay1.getMcNo(), tmStatMfdDay1.getRuleIndex(), returnCode);
                        throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
                    }
                } else {
                    /* 更新数据失败 */
                    rglog.error("更新法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStatMfdDay1.getInstId(), tmStatMfdDay1.getMcNo(), tmStatMfdDay1.getRuleIndex(), returnCode);
                    throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
                }
            }

            //如果当规则不是0 ，则还需要更新规则为0的记录, （走到这，规则肯定不为0）
            if (!CommonConstant.ZERO_COMMON_CONSTANT.equals(tmStatMfdDay1.getRuleIndex())) {
                tmStatMfdDay1.setRuleIndex(CommonConstant.ZERO_COMMON_CONSTANT);

                returnCode = tmStatMfdDayMapper.updateMchntFeeDiscountDayStatistics(tmStatMfdDay1);
                if (CommonConstant.PROCESS_SUCCESS != returnCode) {
                    if (cc.rengu.utility.dbs.Database.DBS_NOT_FOUND == returnCode) {
                        int returnCode2 = tmStatMfdDayMapper.insertTMStatMfdDay(tmStatMfdDay1);
                        if (CommonConstant.PROCESS_SUCCESS != returnCode2) {
                            /* 插入数据失败 */
                            rglog.error("插入法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStatMfdDay1.getInstId(), tmStatMfdDay1.getMcNo(), tmStatMfdDay1.getRuleIndex(), returnCode);
                            throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
                        }
                    } else {
                        /* 更新数据失败 */
                        rglog.error("更新法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStatMfdDay1.getInstId(), tmStatMfdDay1.getMcNo(), tmStatMfdDay1.getRuleIndex(), returnCode);
                        throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
                    }
                }
            }

            /* 手续费减免活动商户单日统计表 */
            TMStatMfdMchntDay tmStatMfdMchntDay1 = new TMStatMfdMchntDay();
            tmStatMfdMchntDay1.setInstId(instId);
            tmStatMfdMchntDay1.setTxnDate(globalTxnDate);
            tmStatMfdMchntDay1.setMcNo(mcNo);
            tmStatMfdMchntDay1.setMchntNo(mchntNo);
            tmStatMfdMchntDay1.setRuleIndex(ruleIndex);
            //本笔交易是最后一笔退款，则更新统计表中的累计笔数
            if (isLastDeal) {
                tmStatMfdMchntDay1.setTotalQtyAcc(CommonConstant.MINUS_ONE_COMMON_CONSTANT);
                tmStatMfdMchntDay1.setTxnQtyAcc(CommonConstant.MINUS_ONE_COMMON_CONSTANT);
            } else {
                tmStatMfdMchntDay1.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                tmStatMfdMchntDay1.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            }
            tmStatMfdMchntDay1.setTotalAmtAcc(totalSubsidyString.toString());
            tmStatMfdMchntDay1.setTxnAmtAcc(orderAmt.toString());
            tmStatMfdMchntDay1.setTotalAvgAmt(CommonConstant.ZERO_AMOUNT);
            tmStatMfdMchntDay1.setExitStatus(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchntDay1.setCashbackStatus(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchntDay1.setCashbackAmt(CommonConstant.ZERO_AMOUNT);
            tmStatMfdMchntDay1.setOprId(CommonConstant.DEFAULT_OPR_ID);
            tmStatMfdMchntDay1.setCreateTime(globalTimeStamp);
            tmStatMfdMchntDay1.setLastOprId(CommonConstant.DEFAULT_OPR_ID);
            tmStatMfdMchntDay1.setUpdateTime(globalTimeStamp);

            rglog.info("机构<{}> 营销活动<{}> 规则<{}> 更新手续费减免活动商户单日统计表...", tmStatMfdMchntDay1.getInstId(), tmStatMfdMchntDay1.getMcNo(), tmStatMfdMchntDay1.getRuleIndex());
            /* 手续费减免活动商户单日统计表 */
            TMStatMfdMchntDayMapper tmStatMfdMchntDayMapper = new TMStatMfdMchntDayMapperImpl();
            int returnCode2 = tmStatMfdMchntDayMapper.updateMchntFeeDiscountMchntDayStatistics(tmStatMfdMchntDay1);
            if (CommonConstant.PROCESS_SUCCESS != returnCode2) {
                if (cc.rengu.utility.dbs.Database.DBS_NOT_FOUND == returnCode) {
                    int returnCode3 = tmStatMfdMchntDayMapper.insertMchntFeeDiscountMchntDayStatistics(tmStatMfdMchntDay1);
                    if (CommonConstant.PROCESS_SUCCESS != returnCode3) {
                        /* 插入数据失败 */
                        rglog.error("插入法人机构<{}> 营销活动<{}> 规则<{}> 更新手续费减免活动商户单日统计表数据失败! RETURN_CODE=<{}>", tmStatMfdDay1.getInstId(), tmStatMfdDay1.getMcNo(), tmStatMfdDay1.getRuleIndex(), returnCode);
                        throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
                    }
                } else {
                    /* 更新数据失败 */
                    rglog.error("更新法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStatMfdMchntDay1.getInstId(), tmStatMfdMchntDay1.getMcNo(), tmStatMfdMchntDay1.getRuleIndex(), returnCode);
                    throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
                }
            }

            //如果当规则不是0 ，则还需要更新规则为0的记录，（走到这，规则肯定不为0）
            if (!CommonConstant.ZERO_COMMON_CONSTANT.equals(tmStatMfdMchntDay1.getRuleIndex())) {
                tmStatMfdMchntDay1.setRuleIndex(CommonConstant.ZERO_COMMON_CONSTANT);

                returnCode2 = tmStatMfdMchntDayMapper.updateMchntFeeDiscountMchntDayStatistics(tmStatMfdMchntDay1);
                if (CommonConstant.PROCESS_SUCCESS != returnCode2) {
                    if (cc.rengu.utility.dbs.Database.DBS_NOT_FOUND == returnCode) {
                        int returnCode3 = tmStatMfdMchntDayMapper.insertMchntFeeDiscountMchntDayStatistics(tmStatMfdMchntDay1);
                        if (CommonConstant.PROCESS_SUCCESS != returnCode3) {
                            /* 插入数据失败 */
                            rglog.error("插入法人机构<{}> 营销活动<{}> 规则<{}> 更新手续费减免活动商户单日统计表数据失败! RETURN_CODE=<{}>", tmStatMfdDay1.getInstId(), tmStatMfdDay1.getMcNo(), tmStatMfdDay1.getRuleIndex(), returnCode);
                            throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
                        }
                    } else {
                        /* 更新数据失败 */
                        rglog.error("更新法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStatMfdMchntDay1.getInstId(), tmStatMfdMchntDay1.getMcNo(), tmStatMfdMchntDay1.getRuleIndex(), returnCode);
                        throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
                    }
                }
            }
        }
    }

    /**
     * 判断规则限制是否达到上限
     *
     * @author liujinan
     * @date 2020/9/23 17:27
     */
    private Boolean judgeIsReachRuleOrMchntLimit(McMchntFeeDiscountTransData mcMchntFeeDiscountTransData, TMStatMfdCriteria tmStatMfdCriteria) throws Exception {

        String instId = tmStatMfdCriteria.getInstId();
        String mcNo = tmStatMfdCriteria.getMcNo();
        String mchntNo = tmStatMfdCriteria.getMchntNo();

        mcMchntFeeDiscountTransData.setInstId(instId);
        mcMchntFeeDiscountTransData.setMcNo(mcNo);
        mcMchntFeeDiscountTransData.setMchntNo(mchntNo);

        //各维度目前的统计值
        //手续费减免活动商户统计 具体规则-累计优惠交易金额
        BigDecimal txnAmtAcc = new BigDecimal(mcMchntFeeDiscountTransData.getMchntTxnAmtAcc());
        //手续费减免活动商户单日统计数据 具体规则-累计优惠金额
        BigDecimal txnAmtAccDay = new BigDecimal(mcMchntFeeDiscountTransData.getMchntDayTxnAmtAcc());
        //规则维度判断是否达到上限使用-规则为指定优惠交易金额
        BigDecimal alredayUseedTxnAmtAccRule = txnAmtAcc.add(txnAmtAccDay);
        //规则维度判断是否达到上限使用-规则为指定优惠手续费金额
        BigDecimal alredayUseedTotalAmtAccRule = new BigDecimal(mcMchntFeeDiscountTransData.getMchntTotalAmtAcc()).add(new BigDecimal(mcMchntFeeDiscountTransData.getMchntDayTotalAmtAcc()));

        rglog.info("机构<{}>营销活动<{}> 规则<{}> 商户<{}> 开始进行规则层面额度是否达到上限判断...", instId, mcNo, mcMchntFeeDiscountTransData.getRuleIndex(), mchntNo);
        //获取当前规则的上限值
        String ruleLimit;

        if (null != tmStatMfdCriteria.getMrctDisUpLmtVal() && !"".equals(tmStatMfdCriteria.getMrctDisUpLmtVal())) {
            rglog.info("营销活动<{}> 商户<{}> 达标统计表 商户优惠上限值 字段有值，直接使用字段值<{}> 作为上限，无需通过计算规则重新计算!", mcNo, mchntNo, tmStatMfdCriteria.getMrctDisUpLmtVal());
            ruleLimit = tmStatMfdCriteria.getMrctDisUpLmtVal();
        } else {
            /* 根据营销活动规则计算商户当前优惠限额 */
            if (FeeCalTypeEnum.TYPE_0.getRuleType().equals(mcMchntFeeDiscountTransData.getCalRuleNo())) {
                /* 无上限，肯定没有达到额度*/
                rglog.info("机构<{}>营销活动<{}> 规则<{}>的计算规则<{}> 规则设置无优惠上限！",
                        instId, mcNo, mcMchntFeeDiscountTransData.getRuleIndex(), mcMchntFeeDiscountTransData.getCalRuleNo());
                ruleLimit = CommonConstant.BIG_NUMBER;
            } else if (FeeCalTypeEnum.TYPE_1.getRuleType().equals(mcMchntFeeDiscountTransData.getCalRuleNo()) ||
                    FeeCalTypeEnum.TYPE_13.getRuleType().equals(mcMchntFeeDiscountTransData.getCalRuleNo())) {
                /* 无需取优惠限额的计算规则,直接使用规则中的限额 */
                ruleLimit = mcMchntFeeDiscountTransData.getDiscountLimit();
                rglog.info("机构<{}>营销活动<{}> 规则<{}>的计算规则<{}> 规则设置指定具体金额<{}>！",
                        instId, mcNo, mcMchntFeeDiscountTransData.getRuleIndex(), mcMchntFeeDiscountTransData.getCalRuleNo(), ruleLimit);
            } else {
                TMPlatCalRule tmPlatCalRule = selectCalculationRuleInfoByPK(instId, mcMchntFeeDiscountTransData.getCalRuleNo());
                if (null == tmPlatCalRule) {
                    /* 未取到营销活动规则信息,本营销活动不可以优惠! */
                    rglog.info("获取机构<{}>的营销活动<{}>的优惠规则<{}>的计算规则<{}>信息匹配,本营销活动不予优惠!",
                            instId, mcNo, mcMchntFeeDiscountTransData.getRuleIndex(), mcMchntFeeDiscountTransData.getCalRuleNo());
                    throw new BizException(RespCodeEnum.GET_MC_RULE_INFO_ERROR.getRespCode(), RespCodeEnum.GET_MC_RULE_INFO_ERROR.getRespDesc());
                }
                //根据规则计算限额值
                ruleLimit = calculateMchntFeeDiscountLimit(instId, mchntNo, tmPlatCalRule.getRuleType(), tmStatMfdCriteria.getCriteriaValue());
                rglog.info("机构<{}>营销活动<{}> 规则<{}>的计算规则<{}> 规则设置上限计算方式<{}>，计算出的值为<{}>！",
                        instId, mcNo, mcMchntFeeDiscountTransData.getRuleIndex(), mcMchntFeeDiscountTransData.getCalRuleNo(), tmPlatCalRule.getRuleType(), ruleLimit);
            }
        }

        if (FeeCalTypeEnum.TYPE_13.getRuleType().equals(mcMchntFeeDiscountTransData.getCalRuleNo())) {
            rglog.info("机构<{}>营销活动<{}> 规则<{}> ,规则限制的为优惠手续费限额!", instId, mcNo, mcMchntFeeDiscountTransData.getRuleIndex());
            if (alredayUseedTotalAmtAccRule.compareTo(new BigDecimal(ruleLimit)) >= CommonConstant.ZERO) {
                rglog.info("机构<{}>营销活动<{}> 规则<{}> ，优惠限额<{}> 规则层面已累计使用额度<{}> 规则层面已达到指定优惠手续费限额，退款不再回退额度",
                        instId, mcNo, mcMchntFeeDiscountTransData.getRuleIndex(), ruleLimit, alredayUseedTotalAmtAccRule);
                return false;
            } else {
            }
        } else {
            rglog.info("机构<{}>营销活动<{}> 规则<{}> ,规则限制的为优惠交易金额限额!", instId, mcNo, mcMchntFeeDiscountTransData.getRuleIndex());
            if (alredayUseedTxnAmtAccRule.compareTo(new BigDecimal(ruleLimit)) >= CommonConstant.ZERO) {
                rglog.info("机构<{}>营销活动<{}> 规则<{}> ，优惠限额<{}> 规则层面已累计使用额度<{}> 规则层面已达到限额，退款不再回退额度",
                        instId, mcNo, mcMchntFeeDiscountTransData.getRuleIndex(), ruleLimit, alredayUseedTxnAmtAccRule);
                return false;
            } else {
            }
        }

        /* 判断单个商户营销活动优惠退出条件 */
        String terminationFlag = mcMchntFeeDiscountTransData.getTerminationFlag();
        //按条件退出
        if (CommonConstant.MCHNT_FEE_EXIT_UNDER_CONDITION.equals(terminationFlag)) {

            /* 单个商户优惠交易笔数上限 */
            BigDecimal quantityLimit = new BigDecimal(mcMchntFeeDiscountTransData.getQuantityLimit());
            /* 单个商户优惠交易金额上限 */
            BigDecimal amountLimit = new BigDecimal(mcMchntFeeDiscountTransData.getAmountLimit());
            if (null != tmStatMfdCriteria.getMrctDisUpLmtVal() && !"".equals(tmStatMfdCriteria.getMrctDisUpLmtVal())) {
                rglog.info("营销活动<{}> 商户<{}> 达标统计表 商户优惠上限值 字段有值，直接使用字段值<{}> 作为上限，无需通过计算规则重新计算!", mcNo, mchntNo, mcMchntFeeDiscountTransData.getMrctDisUpLmtVal());
                amountLimit = new BigDecimal(tmStatMfdCriteria.getMrctDisUpLmtVal());
            } else {
            }
            /* 单个商户手续费优惠额上限 */
            BigDecimal feeLimit = new BigDecimal(mcMchntFeeDiscountTransData.getFeeLimit());

            rglog.info("机构<{}>营销活动<{}> 商户<{}> 开始进行单个商户退出条件层面额度是否达到上限判断...", instId, mcNo, mchntNo);
            //累计优惠笔数
            BigDecimal totalQtyAcc9999 = new BigDecimal(mcMchntFeeDiscountTransData.getMchntTotalQtyAcc9999());
            //累计优惠金额
            BigDecimal totalAmtAcc9999 = new BigDecimal(mcMchntFeeDiscountTransData.getMchntTotalAmtAcc9999());
            //累计交易金额
            BigDecimal txnAmtAcc9999 = new BigDecimal(mcMchntFeeDiscountTransData.getMchntTxnAmtAcc9999());
            //手续费减免活动商户单日统计数据 规则为0-累计优惠笔数
            BigDecimal totalQtyAccDayZero = new BigDecimal(mcMchntFeeDiscountTransData.getMchntDayTotalQtyAccZero());
            //手续费减免活动商户单日统计数据 规则为0-累计优惠金额
            BigDecimal totalAmtAccDayZero = new BigDecimal(mcMchntFeeDiscountTransData.getMchntDayTotalAmtAccZero());
            //手续费减免活动商户单日统计数据 规则为0-累计交易金额
            BigDecimal txnAmtAccDayZero = new BigDecimal(mcMchntFeeDiscountTransData.getMchntDayTxnAmtAccZero());
            //商户维度判断是否达到上限使用
            BigDecimal totalQtyAccMchnt = totalQtyAcc9999.add(totalQtyAccDayZero);
            BigDecimal totalAmtAccMchnt = totalAmtAcc9999.add(totalAmtAccDayZero);
            BigDecimal txnAmtAccMchnt = txnAmtAcc9999.add(txnAmtAccDayZero);

            if (quantityLimit.compareTo(BigDecimal.ZERO) > CommonConstant.ZERO &&
                    totalQtyAccMchnt.compareTo(quantityLimit) >= CommonConstant.ZERO) {
                rglog.info("机构<{}> 营销活动<{}> 单个商户优惠交易笔数上限<{}> 商户已使用额度<{}> 单个商户退出条件已达到限额，退款不再回退额度",
                        instId, mcNo, quantityLimit, totalQtyAccMchnt);
                return false;
            }
            if (feeLimit.compareTo(BigDecimal.ZERO) > CommonConstant.ZERO &&
                    totalAmtAccMchnt.compareTo(feeLimit) >= CommonConstant.ZERO) {
                rglog.info("机构<{}> 营销活动<{}> 单个商户优惠交易手续费上限<{}> 商户已使用额度<{}> 单个商户退出条件已达到限额，退款不再回退额度",
                        instId, mcNo, feeLimit, totalAmtAccMchnt);
                return false;
            }

            if (amountLimit.compareTo(BigDecimal.ZERO) > CommonConstant.ZERO &&
                    txnAmtAccMchnt.compareTo(amountLimit) >= CommonConstant.ZERO) {
                rglog.info("机构<{}> 营销活动<{}> 单个商户优惠交易金额上限<{}> 商户已使用额度<{}> 单个商户退出条件已达到限额，退款不再回退额度",
                        instId, mcNo, amountLimit, txnAmtAccMchnt);
                return false;
            }
        }

        /* 判断活动预算资金是否达到上限 */
        //总预算
        BigDecimal budget = new BigDecimal(mcMchntFeeDiscountTransData.getBudget());
        if (budget.compareTo(BigDecimal.ZERO) > CommonConstant.ZERO) {
            //总预算累计消耗金额
            BigDecimal mcTotalAmtAcc = new BigDecimal(mcMchntFeeDiscountTransData.getMcTotalAmtAcc());
            if (mcTotalAmtAcc.compareTo(budget) >= CommonConstant.ZERO) {
                rglog.info("营销活动<{}>已累计优惠金额<{}> 活动总预算<{}> 达到额度值，不回退额度", mcMchntFeeDiscountTransData.getMcNo(), mcMchntFeeDiscountTransData.getMchntFeeDiscount(), mcMchntFeeDiscountTransData.getBudget());
                return false;
            }
        } else {
            rglog.info("默认预算资金无上限,不判断是否达到预算资金");
        }

        //如果是银行的交易，判断周期维度是否超限
        if (INST_ID_YT.equals(globalInstId)) {
            rglog.info("法人机构<{}> 法人行为银行，需校验手续费优惠活动周期维度额度是否超限!", instId);
            MchntFeeCheckLimitService mchntFeeCheckLimitService = new MchntFeeCheckLimitService();
            if (!mchntFeeCheckLimitService.checkMfdPeriodTotalAmtLimit(mcMchntFeeDiscountTransData, INST_ID_YT, YT_PERIOD_LIMIT, rglog)) {
                return false;
            } else {
            }
        } else {
            rglog.info("法人机构<{}> 法人行无需校验手续费优惠活动周期维度额度是否超限!", instId);
        }

        return true;
    }

    /**
     * 存量商户根据活动编号获取手续费减免类营销活动规则信息表
     *
     * @param instId 法人机构号
     * @param mcNo   营销活动编号
     * @return cc.rengu.igas.momp.common.entity.TMMcMchntFeeDiscountRuleInfo 商户手续费减免类营销活动规则信息表
     * @throws Exception 异常信息
     * @author liujinan
     * @since 2020/9/23 18:01
     */
    private List<TMMcMchntFeeDiscountRuleInfo> getMchntFeeDiscountMcRuleInfo(String instId, String mcNo) throws Exception {

        McRuleInfoMapper mcRuleInfoMapper = new McRuleInfoMapperImpl();
        return mcRuleInfoMapper.selectMchntFeeDiscountRuleInfoList(instId, mcNo);
    }

    /**
     * 获取商户手续费营销活动的活动规则对应的计算规则
     *
     * @param instId 法人机构号
     * @param ruleNo 规则编号
     * @return cc.rengu.igas.momp.common.entity.TMPlatCalRule 计算规则码表
     * @throws Exception 异常信息
     * @author liujinan
     * @date 2020/9/23 17:27
     */
    private TMPlatCalRule selectCalculationRuleInfoByPK(String instId, String ruleNo) throws Exception {

        TMPlatCalRuleMapper tmPlatCalRuleMapper = new TMPlatCalRuleMapperImpl();
        return tmPlatCalRuleMapper.selectCalculationRuleInfoByPrimaryKey(instId, ruleNo);
    }

    /**
     * 根据计算规则计算当前商户手续费优惠限额
     *
     * @throws Exception 异常信息
     * @author liujinan
     * @date 2020/9/23 17:27
     */
    private String calculateMchntFeeDiscountLimit(String instId, String mchntNo, String ruleType, String nowCriteriaValue) throws Exception {

        String month = DateUtil.getFutureMonDay(CommonConstant.MINUS_ONE).substring(0, 6);
        rglog.debug("INST_ID=<{}>, MCHNT_NO=<{}>, MONTH=<{}>", instId, mchntNo, month);

        //商户上月日均余额直接取达标统计表中的当前统计值
        String mchntDeposit = nowCriteriaValue;

        BigDecimal TWO = new BigDecimal("2");
        BigDecimal HUNDARD_1 = new BigDecimal("125");
        BigDecimal HUNDARD_5 = new BigDecimal("500");
        BigDecimal THOUSAND_30 = new BigDecimal("30000");
        BigDecimal THOUSAND_50 = new BigDecimal("50000");
        BigDecimal THOUSAND_100 = new BigDecimal("100000");

        BigDecimal deposit = new BigDecimal(mchntDeposit).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
        BigDecimal tenThousand = new BigDecimal("10000").setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
        BigDecimal discountLimit;

        if (null != ruleType) {
            switch (FeeCalTypeEnum.getByValue(ruleType)) {
                case TYPE_2:
                    /* 上月日均存款万位取整+3万 */
                    discountLimit = deposit.divideToIntegralValue(tenThousand).add(THOUSAND_30);
                    break;
                case TYPE_3:
                    /* 上月日均存款*2+3万 */
                    discountLimit = deposit.multiply(TWO).add(THOUSAND_30);
                    break;
                case TYPE_4:
                    /* 上月日均存款万位取整+5万 */
                    discountLimit = deposit.divideToIntegralValue(tenThousand).add(THOUSAND_50);
                    break;
                case TYPE_5:
                    /* 上月日均存款*2+5万 */
                    discountLimit = deposit.multiply(TWO).add(THOUSAND_50);
                    break;
                case TYPE_6:
                    /* 上月日均存款每10万优惠125元 */
                    discountLimit = deposit.divide(THOUSAND_100).multiply(HUNDARD_1);
                    break;
                case TYPE_7:
                    /* 上月日均存款每10万优惠500元 */
                    discountLimit = deposit.divide(THOUSAND_100).multiply(HUNDARD_5);
                    break;
                case TYPE_8:
                    /* 上月日均存款 */
                    discountLimit = deposit;
                    break;
                case TYPE_9:
                    /* 上月日均存款每万元取整*2+3万 */
                    rglog.info("手续费计算规则类型 <{}> 上月日均存款每万元*2+3万", ruleType);
                    discountLimit = deposit.divideToIntegralValue(tenThousand).multiply(TWO).multiply(tenThousand).add(THOUSAND_30);
                    break;
                case TYPE_10:
                    /* 上月日均存款每万元*2+5万 */
                    rglog.info("手续费计算规则类型 <{}> 上月日均存款每万元*2+5万", ruleType);
                    discountLimit = deposit.divideToIntegralValue(tenThousand).multiply(TWO).multiply(tenThousand).add(THOUSAND_50);
                    break;
                case TYPE_11:
                    /* 上月日均存款每十万元*2+3万 */
                    rglog.info("手续费计算规则类型 <{}> 上月日均存款每十万元*2+3万", ruleType);
                    discountLimit = deposit.divideToIntegralValue(THOUSAND_100).multiply(THOUSAND_100).multiply(TWO).add(THOUSAND_30);
                    break;
                case TYPE_12:
                    /* 上月日均存款每十万元*2+5万 */
                    rglog.info("手续费计算规则类型 <{}> 上月日均存款每十万元*2+5万", ruleType);
                    discountLimit = deposit.divideToIntegralValue(THOUSAND_100).multiply(THOUSAND_100).multiply(TWO).add(THOUSAND_50);
                    break;
                default:
                    discountLimit = BigDecimal.ZERO;
            }
            rglog.info("规则层面优惠交易金额上限 DISCOUNT_LIMIT=<{}>", discountLimit.setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).toString());
            return discountLimit.toString();
        } else {
            return CommonConstant.ZERO_AMOUNT;
        }
    }

    /**
     * 取商户手续费优惠类营销活动各维度统计数据
     *
     * @param mcMchntFeeDiscountTransData
     * @return int 返回码
     * @throws Exception 异常信息
     * @author liujinan
     * @since 2020/9/25 20:22
     */
    private void fetchAllMchntFeeDiscountMcQuotaData(McMchntFeeDiscountTransData mcMchntFeeDiscountTransData, TMStatMfdCriteria tmStatMfdCriteria) throws Exception {

        //规则维度批量处理状态
        int batchStatus = CommonConstant.FLAG_NOT_SET;
        int batchStatus_stat_mfd = CommonConstant.FLAG_NOT_SET;
        String instId = tmStatMfdCriteria.getInstId();
        String mcNo = tmStatMfdCriteria.getMcNo();
        String mchntNo = tmStatMfdCriteria.getMchntNo();
        String periodStartDate = tmStatMfdCriteria.getPeriodStartDate();
        String periodEndDate = tmStatMfdCriteria.getPeriodEndDate();
        String lastDate = DateUtil.getBaseDateOffsetDay(globalTxnDate, CommonConstant.MINUS_ONE);
        String lastSecondDate = DateUtil.getBaseDateOffsetDay(lastDate, CommonConstant.MINUS_ONE);

        /* 商户取营销活动规则信息 */
        List<TMMcMchntFeeDiscountRuleInfo> tmMcMchntFeeDiscountRuleInfoList = getMchntFeeDiscountMcRuleInfo(instId, mcNo);
        if (null == tmMcMchntFeeDiscountRuleInfoList || tmMcMchntFeeDiscountRuleInfoList.isEmpty()) {
            /* 未取到营销活动规则信息! */
            rglog.info("获取机构<{}>的营销活动<{}>营销活动规则信息失败!", instId, mcNo);
            throw new BizException(RespCodeEnum.GET_MC_RULE_INFO_ERROR.getRespCode(), RespCodeEnum.GET_MC_RULE_INFO_ERROR.getRespDesc());
        }

        /* 代码判断匹配到了哪条规则上 */
        TMMcMchntFeeDiscountRuleInfo tmMcMchntFeeDiscountRuleInfo;
        BigDecimal criteriaValue = new BigDecimal(tmStatMfdCriteria.getCriteriaValue()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);

        List<TMMcMchntFeeDiscountRuleInfo> tmMcMchntFeeDiscountRuleInfoList1 = new ArrayList<>();
        for (TMMcMchntFeeDiscountRuleInfo tmMcMchntFeeDiscountRuleInfo1 : tmMcMchntFeeDiscountRuleInfoList) {

            BigDecimal floor = new BigDecimal(tmMcMchntFeeDiscountRuleInfo1.getCriteriaFloor()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
            BigDecimal celling = new BigDecimal(tmMcMchntFeeDiscountRuleInfo1.getCriteriaCelling()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);

            /* 按照左包右不包原则判断 */
            if (CommonConstant.ZERO <= criteriaValue.compareTo(floor) && CommonConstant.ZERO > criteriaValue.compareTo(celling)) {
                tmMcMchntFeeDiscountRuleInfoList1.add(tmMcMchntFeeDiscountRuleInfo1);
            }
        }

        if (tmMcMchntFeeDiscountRuleInfoList1.isEmpty()) {
            /* 判断是否是因为当前统计指超过最高档规则上限,是的话按照最高档规则进行计算 */
            tmMcMchntFeeDiscountRuleInfo = tmMcMchntFeeDiscountRuleInfoList.stream().max(Comparator.comparing(TMMcMchntFeeDiscountRuleInfo::getRuleIndex)).get();
            BigDecimal celling = new BigDecimal(tmMcMchntFeeDiscountRuleInfo.getCriteriaCelling()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
            if (CommonConstant.ZERO >= celling.compareTo(criteriaValue)) {
                rglog.info("当前商户<{}>的达标统计值<{}>超过最高一档规则上限<{}>,按照该档规则计算!", mchntNo, criteriaValue.toString(), celling.toString());
            } else {
                rglog.info("获取机构<{}>的营销活动<{}>优惠规则信息匹配失败,无满足条件的规则!", instId, mcNo);
                throw new BizException(RespCodeEnum.GET_MC_RULE_INFO_ERROR.getRespCode(), RespCodeEnum.GET_MC_RULE_INFO_ERROR.getRespDesc());
            }
        } else {
            rglog.info("当前商户<{}>,营销活动<{}>符合的规则条数为<{}>,如果多余一条，则取规则号最大的!", mchntNo, mcNo, tmMcMchntFeeDiscountRuleInfoList1.size());
            if (CommonConstant.ONE != tmMcMchntFeeDiscountRuleInfoList1.size()) {
                /* 超过1条以上规则符合条件 */
                tmMcMchntFeeDiscountRuleInfo = tmMcMchntFeeDiscountRuleInfoList1.stream().max(Comparator.comparing(TMMcMchntFeeDiscountRuleInfo::getRuleIndex)).get();
            } else {
                tmMcMchntFeeDiscountRuleInfo = tmMcMchntFeeDiscountRuleInfoList1.get(CommonConstant.ZERO);
            }
        }
        convertMchntFeeDiscountMcRuleInfo(tmMcMchntFeeDiscountRuleInfo, mcMchntFeeDiscountTransData);
        //退款交易时，所对应的规则号
        String ruleIndex = tmMcMchntFeeDiscountRuleInfo.getRuleIndex();
        //查询营销活动信息
        rglog.info("获取营销活动<{}>基本信息", mcNo);
        TMMcMchntFeeDiscountInfo tmMcMchntFeeDiscountInfo = getMchntFeeDiscountMcInfo(instId, mcNo);
        if (null == tmMcMchntFeeDiscountInfo) {
            rglog.error("机构<{}>的商户<{}>未获取到商户手续费优惠营销活动信息!", instId, mchntNo);
            throw new BizException(RespCodeEnum.GET_MONEY_OFF_MC_DETAIL_ERROR.getRespCode(), RespCodeEnum.GET_MONEY_OFF_MC_DETAIL_ERROR.getRespDesc());
        }
        convertMchntFeeDiscountMcInfo(tmMcMchntFeeDiscountInfo, mcMchntFeeDiscountTransData);

        String mcStartDate = tmMcMchntFeeDiscountInfo.getMcStartDate();
        String mcType = tmMcMchntFeeDiscountInfo.getMcType();

        /*------------------------------------------------查询营销活动商户维度汇总数据------------------------------------*/
        /* 查询商户手续费优惠营销活动商户统计表数据  查询具体规则维度的统计数值*/
        TMStatMfdMchnt tmStatMfdMchnt = selectMchntFeeDiscountMchntStatisticsByPK(instId, mcNo, ruleIndex, mchntNo, periodStartDate, periodEndDate);
        if (null == tmStatMfdMchnt) {
            rglog.info("机构<{}>的营销活动<{}>的规则<{}>商户手续费优惠营销活动商户统计表数据查询失败!", globalInstId, mcNo, ruleIndex);

            /* 取到0条数据,说明该营销活动还未产生统计值,按所有统计值都是0进行处理 */
            tmStatMfdMchnt = new TMStatMfdMchnt();
            tmStatMfdMchnt.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchnt.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchnt.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchnt.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
        }

        /* 查询商户手续费优惠营销活动商户单日统计表数据 具体规则编号的数据*/
        TMStatMfdMchntDay tmStatMfdMchntDay = selectMchntFeeDiscountMchntDayStatisticsByPK(instId, mcNo, ruleIndex, mchntNo, globalTxnDate);
        if (null == tmStatMfdMchntDay) {
            rglog.error("机构<{}> 商户<{}> 商户手续费优惠营销活动<{}> 规则<{}> 商户手续费优惠营销活动商户单日统计表数据查询失败!", instId, mchntNo, mcNo, ruleIndex);
            tmStatMfdMchntDay = new TMStatMfdMchntDay();
            tmStatMfdMchntDay.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchntDay.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchntDay.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchntDay.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
        }

        /* 查询商户手续费优惠营销活动商户单日统计表数据  规则为0的数据*/
        TMStatMfdMchntDay tmStatMfdMchntDayRuleZero = selectMchntFeeDiscountMchntDayStatisticsByPK(instId, mcNo, CommonConstant.ZERO_COMMON_CONSTANT, mchntNo, globalTxnDate);
        if (null == tmStatMfdMchntDayRuleZero) {
            rglog.error("机构<{}> 商户<{}> 商户手续费优惠营销活动<{}> 规则<{}> 商户手续费优惠营销活动商户单日统计表数据查询失败!", instId, mchntNo, mcNo, CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchntDayRuleZero = new TMStatMfdMchntDay();
            tmStatMfdMchntDayRuleZero.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchntDayRuleZero.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchntDayRuleZero.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchntDayRuleZero.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
        }

        /* 查询商户手续费优惠营销活动商户统计表数据  查询规则为9999的数据，这个统计的是营销活动配置商户退出条件时，统计周期内的所有规则的统计值 如单个商户是季度统计，规则是月度统计，这个9999是当前季度的统计*/
        TMStatMfdMchnt tmStatMfdMchnt9999 = selectNowPeriodDateTMStatMfdMchnt(instId, mcNo, CommonConstant.RULE_NINE, mchntNo, globalTxnDate);
        if (null == tmStatMfdMchnt9999) {
            rglog.info("机构<{}>的营销活动<{}>的规则<{}>商户手续费优惠营销活动商户统计表数据查询失败!", globalInstId, mcNo, CommonConstant.RULE_NINE);

            /* 取到0条数据,说明该营销活动还未产生统计值,按所有统计值都是0进行处理 */
            tmStatMfdMchnt9999 = new TMStatMfdMchnt();
            tmStatMfdMchnt9999.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchnt9999.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchnt9999.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchnt9999.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
        }
        String batchDate;
        //查询统计信息备份表批次信息 查询营销活动信息表的批量处理情况即可
        String statPrimaryKey = "FeeMchnt" + instId + "_" + mcNo;
        TMStatBak tmStatBak = selectTMStatBakByStatPrimaryKey(globalInstId, mcType, statPrimaryKey);
        //批次表为空，从来没执行过批量任务
        if (null == tmStatBak) {
            //从来没执行过批量任务，则从活动开始的第一天开始取数据
            batchDate = mcStartDate;
        } else {
            batchDate = DateUtil.getBaseDateOffsetDay(tmStatBak.getBatchDate(), 1);
        }
        //批量处理的日期小于昨天的日期，则需要取之前的数据
        while (DateUtil.compareDate(batchDate, lastDate) <= 0) {
            //获取的数据累加到活动统计中
            /* 查询商户手续费优惠营销活动商户单日统计表数据 具体规则编号的数据*/
            TMStatMfdMchntDay newtmStatMfdMchntDay = selectMchntFeeDiscountMchntDayStatisticsByPK(instId, mcNo, ruleIndex, mchntNo, batchDate);
            if (null == newtmStatMfdMchntDay) {
                rglog.error("机构<{}> 商户<{}> 商户手续费优惠营销活动<{}> 规则<{}> 商户手续费优惠营销活动商户单日统计表数据查询失败!", instId, mchntNo, mcNo, ruleIndex);
                newtmStatMfdMchntDay = new TMStatMfdMchntDay();
                newtmStatMfdMchntDay.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                newtmStatMfdMchntDay.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                newtmStatMfdMchntDay.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                newtmStatMfdMchntDay.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            }
            /* 查询商户手续费优惠营销活动商户单日统计表数据  规则为0的数据*/
            TMStatMfdMchntDay newtmStatMfdMchntDayRuleZero = selectMchntFeeDiscountMchntDayStatisticsByPK(instId, mcNo, CommonConstant.ZERO_COMMON_CONSTANT, mchntNo, batchDate);
            if (null == newtmStatMfdMchntDayRuleZero) {
                rglog.error("机构<{}> 商户<{}> 商户手续费优惠营销活动<{}> 规则<{}> 商户手续费优惠营销活动商户单日统计表数据查询失败!", instId, mchntNo, mcNo, CommonConstant.ZERO_COMMON_CONSTANT);
                newtmStatMfdMchntDayRuleZero = new TMStatMfdMchntDay();
                newtmStatMfdMchntDayRuleZero.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                newtmStatMfdMchntDayRuleZero.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                newtmStatMfdMchntDayRuleZero.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                newtmStatMfdMchntDayRuleZero.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            }
            //将单日统计表的数据累加到周期数据上
            if (DateUtil.compareDate(batchDate, periodStartDate) < 0) {
                rglog.error("获取日期<{}>的单日统计不属于在本统计周期中，不需要累加到商户统计表!", batchDate);
            } else {
                rglog.error("获取日期<{}>的单日统计属于在本统计周期中，需要累加到商户统计表!", batchDate);
                copyMchntStatMfdData(tmStatMfdMchnt, newtmStatMfdMchntDay);
                copyMchntStatMfdData(tmStatMfdMchnt9999, newtmStatMfdMchntDayRuleZero);
            }
            //将批次日期加一天继续判断
            batchDate = DateUtil.getBaseDateOffsetDay(batchDate, 1);
        }

        copyMchntFeeDiscountMchntStatData(tmStatMfdMchnt, mcMchntFeeDiscountTransData);
        copyMchntFeeDiscountMchntDayStatData(tmStatMfdMchntDay, mcMchntFeeDiscountTransData);
        copyMchntFeeDiscountMchntStat9999Data(tmStatMfdMchnt9999, mcMchntFeeDiscountTransData);
        copyMchntFeeDiscountMchntDayZeroStatData(tmStatMfdMchntDayRuleZero, mcMchntFeeDiscountTransData);
        /*------------------------------------------------查询营销活动维度汇总数据------------------------------------*/
        /* 查询商户手续费优惠营销活动统计表数据  规则为0的数据*/
        //查询统计信息备份表批次信息 查询营销活动信息表的批量处理情况即可
        statPrimaryKey = "Fee" + instId + "_" + mcNo;
        tmStatBak = selectTMStatBakByStatPrimaryKey(instId, McTypeEnum.MCHNT_FEE_DISCOUNT.getMcTypeCode(), statPrimaryKey);
        //批次表为空，从来没执行过批量任务
        if (null == tmStatBak) {
            //从来没执行过批量任务，则从活动开始的第一天开始取数据
            batchDate = mcStartDate;
        } else {
            batchDate = DateUtil.getBaseDateOffsetDay(tmStatBak.getBatchDate(), 1);
        }
        /* 查询商户手续费优惠营销活动统计表数据  规则为0的数据*/
        TMStatMfd tmStatMfd = selectMchntFeeDiscountStatisticsByPK(instId, mcNo, CommonConstant.ZERO_COMMON_CONSTANT);
        if (null == tmStatMfd) {
            rglog.info("机构<{}>的营销活动<{}>的规则<{}>商户手续费优惠营销活动统计表数据查询失败!", globalInstId, mcNo, CommonConstant.ZERO_COMMON_CONSTANT);

            /* 取到0条数据,说明该营销活动还未产生统计值,按所有统计值都是0进行处理 */
            tmStatMfd = new TMStatMfd();
            tmStatMfd.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfd.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfd.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfd.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);

        }

        /* 查询商户手续费优惠营销活动单日统计表数据 规则为0的数据*/
        TMStatMfdDay tmStatMfdDay = selectMchntFeeDiscountDayStatisticsByPK(instId, mcNo, CommonConstant.ZERO_COMMON_CONSTANT, globalTxnDate);
        if (null == tmStatMfdDay) {
            rglog.error("机构<{}>的商户手续费优惠营销活动<{}>的规则<{}> 手续费减免活动单日统计表 数据查询失败!", instId, mcNo, CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdDay = new TMStatMfdDay();
            tmStatMfdDay.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdDay.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdDay.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdDay.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
        }
        //批量处理的日期小于昨天的日期，则需要取之前的数据
        while (DateUtil.compareDate(batchDate, lastDate) <= 0) {
            //循环获取单日统计表数据并累加
            /* 查询商户手续费优惠营销活动单日统计表数据 规则为0的数据*/
            TMStatMfdDay tmStatMfdDay2 = selectMchntFeeDiscountDayStatisticsByPK(instId, mcNo, CommonConstant.ZERO_COMMON_CONSTANT, batchDate);
            if (null == tmStatMfdDay2) {
                rglog.error("机构<{}>的商户手续费优惠营销活动<{}>的规则<{}> 手续费减免活动单日统计表 数据查询失败!", instId, mcNo, CommonConstant.ZERO_COMMON_CONSTANT);
                tmStatMfdDay2 = new TMStatMfdDay();
                tmStatMfdDay2.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                tmStatMfdDay2.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                tmStatMfdDay2.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                tmStatMfdDay2.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            }
            copyStatMfdData(tmStatMfd, tmStatMfdDay2);
            //将批次日期加一天继续判断
            batchDate = DateUtil.getBaseDateOffsetDay(batchDate, 1);
        }
        //将累计优惠手续费金额赋值
        copyMchntFeeDiscountZeroStatData(tmStatMfd, tmStatMfdDay, mcMchntFeeDiscountTransData);

        /*------------------------------------------------查询营销活动周期维度汇总数据------------------------------------*/
        //查询统计信息备份表批次信息 查询营销活动信息表的批量处理情况即可
        //批次表为空，从来没执行过批量任务
        if (null == tmStatBak) {
            //从来没执行过批量任务，则从活动开始的第一天开始取数据
            batchDate = mcStartDate;
        } else {
            batchDate = DateUtil.getBaseDateOffsetDay(tmStatBak.getBatchDate(), 1);
        }
        /* 查询商户手续费减免活动周期统计表数据  规则为0的数据*/
        TMStatMfdPeriod tmStatMfdPeriod = selectMchntFeeDiscountPeriodStatisticsByPK(instId, mcNo, CommonConstant.ZERO_COMMON_CONSTANT, globalTxnDate, globalTxnDate);
        if (null == tmStatMfdPeriod) {
            rglog.info("机构<{}>的营销活动<{}>的规则<{}>商户手续费减免活动周期统计表数据查询结果为空!", globalInstId, mcNo, CommonConstant.ZERO_COMMON_CONSTANT);
            /* 取到0条数据,说明该营销活动还未产生统计值,按所有统计值都是0进行处理 */
            tmStatMfdPeriod = new TMStatMfdPeriod();
            tmStatMfdPeriod.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdPeriod.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdPeriod.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdPeriod.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            //获取不到周期统计数据，默认按照自然月度配置周期起始日期
            tmStatMfdPeriod.setPeriodStartDate(MompDateUtil.getSecondDay(Integer.parseInt(globalTxnDate.substring(0, 4)), Integer.parseInt(globalTxnDate.substring(4, 6))));
        } else {
            rglog.info("机构<{}>的营销活动<{}>的规则<{}> 商户手续费减免活动周期统计表数据查询结束!", globalInstId, mcNo, CommonConstant.ZERO_COMMON_CONSTANT);
        }

        //批量处理的日期小于昨天的日期，则需要取之前的数据
        while (DateUtil.compareDate(batchDate, lastDate) <= 0) {
            //循环获取单日统计表数据并累加
            /* 查询商户手续费优惠营销活动单日统计表数据 规则为0的数据*/
            rglog.error("机构<{}> 手续费优惠营销活动<{}> 规则<{}> 获取日期为<{}> 手续费减免活动单日统计表数据...", instId, mcNo, ruleIndex, batchDate);
            TMStatMfdDay tmStatMfdDay2 = selectMchntFeeDiscountDayStatisticsByPK(instId, mcNo, CommonConstant.ZERO_COMMON_CONSTANT, batchDate);
            if (null == tmStatMfdDay2) {
                rglog.error("机构<{}>的商户手续费优惠营销活动<{}>的规则<{}> 手续费减免活动单日统计表 数据查询失败!", instId, mcNo, ruleIndex);
                tmStatMfdDay2 = new TMStatMfdDay();
                tmStatMfdDay2.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                tmStatMfdDay2.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                tmStatMfdDay2.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                tmStatMfdDay2.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            }
            //将单日统计表的数据累加到周期数据上
            if (DateUtil.compareDate(batchDate, tmStatMfdPeriod.getPeriodStartDate()) < 0) {
                rglog.error("获取日期<{}>的单日统计不属于在本统计周期中，需要累加到周期统计表!", batchDate);
            } else {
                rglog.error("获取日期<{}>的单日统计属于在本统计周期中，需要累加到周期统计表!", batchDate);
                copyMchntFeeDiscountMchntStatData(tmStatMfdPeriod, tmStatMfdDay2);
            }
            //将批次日期加一天继续判断
            batchDate = DateUtil.getBaseDateOffsetDay(batchDate, 1);
        }
        //将累计优惠手续费金额赋值——周期维度判断使用
        copyMchntFeeDiscountPeriodZeroStatData(tmStatMfdPeriod, tmStatMfdDay, mcMchntFeeDiscountTransData);
    }

    /**
     * 手续费减免活动商户统计数据赋值
     *
     * @param tmStatMfdMchnt              手续费减免活动商户统计表
     * @param mcMchntFeeDiscountTransData 操作对象
     * @author liujinan
     * @since 2020/6/5 11:23
     */
    private void copyMchntFeeDiscountMchntStatData(TMStatMfdMchnt tmStatMfdMchnt, McMchntFeeDiscountTransData mcMchntFeeDiscountTransData) {

        /* 手续费减免活动商户统计-累计优惠笔数 */
        mcMchntFeeDiscountTransData.setMchntTotalQtyAcc(tmStatMfdMchnt.getTotalQtyAcc());
        /* 手续费减免活动商户统计-累计优惠金额 */
        mcMchntFeeDiscountTransData.setMchntTotalAmtAcc(tmStatMfdMchnt.getTotalAmtAcc());
        /* 手续费减免活动商户统计-累计交易笔数 */
        mcMchntFeeDiscountTransData.setMchntTxnQtyAcc(tmStatMfdMchnt.getTxnQtyAcc());
        /* 手续费减免活动商户统计-累计交易金额 */
        mcMchntFeeDiscountTransData.setMchntTxnAmtAcc(tmStatMfdMchnt.getTxnAmtAcc());
    }

    /**
     * 手续费减免活动商户单日统计数据赋值
     *
     * @param tmStatMfdMchntDay           手续费减免活动商户单日统计表
     * @param mcMchntFeeDiscountTransData 操作对象
     * @author liujinan
     * @since 2020/6/5 11:22
     */
    private void copyMchntFeeDiscountMchntDayStatData(TMStatMfdMchntDay tmStatMfdMchntDay, McMchntFeeDiscountTransData mcMchntFeeDiscountTransData) {

        /* 手续费减免活动商户单日统计数据-累计优惠笔数 */
        mcMchntFeeDiscountTransData.setMchntDayTotalQtyAcc(tmStatMfdMchntDay.getTotalQtyAcc());
        /* 手续费减免活动商户单日统计数据-累计优惠金额 */
        mcMchntFeeDiscountTransData.setMchntDayTotalAmtAcc(tmStatMfdMchntDay.getTotalAmtAcc());
        /* 手续费减免活动商户单日统计数据-累计交易笔数 */
        mcMchntFeeDiscountTransData.setMchntDayTxnQtyAcc(tmStatMfdMchntDay.getTxnQtyAcc());
        /* 手续费减免活动商户单日统计数据-累计交易金额 */
        mcMchntFeeDiscountTransData.setMchntDayTxnAmtAcc(tmStatMfdMchntDay.getTxnAmtAcc());
    }

    /**
     * 手续费减免活动商户统计数据(商户维度)赋值
     *
     * @param tmStatMfdMchnt 手续费减免活动商户统计表
     * @author liujinan
     * @since 2020/9/24 11:23
     */
    private void copyMchntFeeDiscountMchntStat9999Data(TMStatMfdMchnt tmStatMfdMchnt, McMchntFeeDiscountTransData mcMchntFeeDiscountTransData) {

        /* 总预算累计优惠笔数 */
        mcMchntFeeDiscountTransData.setMchntTotalQtyAcc9999(tmStatMfdMchnt.getTotalQtyAcc());
        /* 总预算累计优惠金额 */
        mcMchntFeeDiscountTransData.setMchntTotalAmtAcc9999(tmStatMfdMchnt.getTotalAmtAcc());
        /* 总预算累计交易笔数 */
        mcMchntFeeDiscountTransData.setMchntTxnQtyAcc9999(tmStatMfdMchnt.getTxnQtyAcc());
        /* 总预算累计交易金额 */
        mcMchntFeeDiscountTransData.setMchntTxnAmtAcc9999(tmStatMfdMchnt.getTxnAmtAcc());
    }

    /**
     * 手续费减免活动商户单日统计数据赋值 规则为0的统计数据
     *
     * @param tmStatMfdMchntDay           手续费减免活动商户单日统计表
     * @param mcMchntFeeDiscountTransData 操作对象
     * @author liujinan
     * @since 2020/9/25 11:22
     */
    private void copyMchntFeeDiscountMchntDayZeroStatData(TMStatMfdMchntDay tmStatMfdMchntDay, McMchntFeeDiscountTransData mcMchntFeeDiscountTransData) {

        /* 手续费减免活动商户单日统计数据-累计优惠笔数 */
        mcMchntFeeDiscountTransData.setMchntDayTotalQtyAccZero(tmStatMfdMchntDay.getTotalQtyAcc());
        /* 手续费减免活动商户单日统计数据-累计优惠金额 */
        mcMchntFeeDiscountTransData.setMchntDayTotalAmtAccZero(tmStatMfdMchntDay.getTotalAmtAcc());
        /* 手续费减免活动商户单日统计数据-累计交易笔数 */
        mcMchntFeeDiscountTransData.setMchntDayTxnQtyAccZero(tmStatMfdMchntDay.getTxnQtyAcc());
        /* 手续费减免活动商户单日统计数据-累计交易金额 */
        mcMchntFeeDiscountTransData.setMchntDayTxnAmtAccZero(tmStatMfdMchntDay.getTxnAmtAcc());
    }

    /**
     * 使用主键取手续费减免活动商户统计表单条数据
     *
     * @param instId
     * @param mcNo
     * @param ruleIndex
     * @param mchntNo
     * @return cc.rengu.igas.momp.common.entity.TMStatMfdMchnt
     * @throws Exception
     * @author liujinan
     * @date 2020/9/15
     */
    private TMStatMfdMchnt selectNowPeriodDateTMStatMfdMchnt(String instId, String mcNo, String ruleIndex, String mchntNo, String txnDate) throws Exception {

        TMStatMfdMchntMapper tmStatMfdMchntMapper = new TMStatMfdMchntMapperImpl();
        return tmStatMfdMchntMapper.selectNowPeriodDateTMStatMfdMchnt(instId, mcNo, ruleIndex, mchntNo, txnDate);
    }

    /**
     * 使用主键取手续费减免活动商户统计表单条数据
     *
     * @param instId          法人机构号
     * @param mcNo            营销活动编号
     * @param ruleIndex       规则顺序号
     * @param mchntNo         商户编号
     * @param periodStartDate 统计周期起始日期
     * @param periodEndDate   统计周期结束日期
     * @return cc.rengu.igas.momp.common.entity.TMStatMfdMchnt 手续费减免活动商户统计表
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/4/20 23:40
     */
    private TMStatMfdMchnt selectMchntFeeDiscountMchntStatisticsByPK(String instId, String mcNo, String ruleIndex, String mchntNo, String periodStartDate, String periodEndDate) throws Exception {

        TMStatMfdMchntMapper tmStatMfdMchntMapper = new TMStatMfdMchntMapperImpl();
        return tmStatMfdMchntMapper.selectMchntFeeDiscountMchntStatisticsByPK(instId, mcNo, ruleIndex, mchntNo, periodStartDate, periodEndDate);
    }

    /**
     * 使用营销活动商户信息对象获取商户手续费优惠类营销活动基本信息
     *
     * @param instId 法人机构号
     * @param mcNo   营销活动编号
     * @return cc.rengu.igas.momp.common.entity.TMMcMchntFeeDiscountInfo 商户手续费减免类营销活动信息表
     * @throws Exception 异常信息
     * @author liujinan
     * @since 2020/9/25 14:14
     */
    private TMMcMchntFeeDiscountInfo getMchntFeeDiscountMcInfo(String instId, String mcNo) throws Exception {

        McDetailInfoMapper mcDetailInfoMapper = new McDetailInfoMapperImpl();
        return mcDetailInfoMapper.selectMchntFeeDiscountMcDetailInfo(instId, mcNo);
    }

    /**
     * 商户手续费优惠营销活动规则信息转换
     *
     * @param tmMcMchntFeeDiscountRuleInfo 商户手续费减免类营销活动规则信息表
     * @author liujinan
     * @since 2020/4/20 20:47
     */
    private void convertMchntFeeDiscountMcRuleInfo(TMMcMchntFeeDiscountRuleInfo tmMcMchntFeeDiscountRuleInfo, McMchntFeeDiscountTransData mcMchntFeeDiscountTransData) {

        /* 顺序号 */
        mcMchntFeeDiscountTransData.setRuleIndex(tmMcMchntFeeDiscountRuleInfo.getRuleIndex());
        /* 控制下限 */
        mcMchntFeeDiscountTransData.setCriteriaFloor(tmMcMchntFeeDiscountRuleInfo.getCriteriaFloor());
        /* 控制上限 */
        mcMchntFeeDiscountTransData.setCriteriaCelling(tmMcMchntFeeDiscountRuleInfo.getCriteriaCelling());
        /* 优惠周期 */
        mcMchntFeeDiscountTransData.setDiscountPeriod(tmMcMchntFeeDiscountRuleInfo.getDiscountPeriod());
        /* 优惠类型 */
        mcMchntFeeDiscountTransData.setDiscountType(tmMcMchntFeeDiscountRuleInfo.getDiscountType());
        /* 优惠力度 */
        mcMchntFeeDiscountTransData.setDiscount(tmMcMchntFeeDiscountRuleInfo.getDiscount());
        /* 计算规则编号 */
        mcMchntFeeDiscountTransData.setCalRuleNo(tmMcMchntFeeDiscountRuleInfo.getCalRuleNo());
        /* 优惠上限 */
        mcMchntFeeDiscountTransData.setDiscountLimit(tmMcMchntFeeDiscountRuleInfo.getDiscountLimit());
    }

    /**
     * 商户手续费优惠营销活动信息转换
     *
     * @param tmMcMchntFeeDiscountInfo 商户手续费减免类营销活动信息表
     * @throws Exception 异常信息
     * @author liujinan
     * @since 2020/9/25 17:14
     */
    private void convertMchntFeeDiscountMcInfo(TMMcMchntFeeDiscountInfo tmMcMchntFeeDiscountInfo, McMchntFeeDiscountTransData mcMchntFeeDiscountTransData) throws Exception {

        /* 营销活动编号 */
        mcMchntFeeDiscountTransData.setMcNo(tmMcMchntFeeDiscountInfo.getMcNo());
        /* 营销活动名称 */
        mcMchntFeeDiscountTransData.setMcName(tmMcMchntFeeDiscountInfo.getMcName());
        /* 营销活动类型 */
        mcMchntFeeDiscountTransData.setMcType(tmMcMchntFeeDiscountInfo.getMcType());
        /* 营销活动状态 */
        mcMchntFeeDiscountTransData.setMcStatus(tmMcMchntFeeDiscountInfo.getMcStatus());
        /* 活动起始日期 */
        mcMchntFeeDiscountTransData.setMcStartDate(tmMcMchntFeeDiscountInfo.getMcStartDate());
        /* 活动截止日期 */
        mcMchntFeeDiscountTransData.setMcEndDate(tmMcMchntFeeDiscountInfo.getMcEndDate());
        /* 活动结束日期 */
        mcMchntFeeDiscountTransData.setMcActualEndDate(tmMcMchntFeeDiscountInfo.getMcActualEndDate());
        /* 存量商户达标条件 */
        mcMchntFeeDiscountTransData.setStockMchntFlag(tmMcMchntFeeDiscountInfo.getStockMchntFlag());
        /* 存量商户支持类型 */
        mcMchntFeeDiscountTransData.setStockMchntType(tmMcMchntFeeDiscountInfo.getStockMchntType());
        /* 有效交易下限 */
        mcMchntFeeDiscountTransData.setEffectiveLimit(tmMcMchntFeeDiscountInfo.getEffectiveLimit());
        /* 新增商户活动标志 */
        mcMchntFeeDiscountTransData.setNewMchntFlag(tmMcMchntFeeDiscountInfo.getNewMchntFlag());
        /* 新增商户免手续费周期 */
        mcMchntFeeDiscountTransData.setNewMchntPeriod(tmMcMchntFeeDiscountInfo.getNewMchntPeriod());
        /* 新增商户周期顺延标志 */
        mcMchntFeeDiscountTransData.setPostponeFlag(tmMcMchntFeeDiscountInfo.getPostponeFlag());
        /* 达标前手续费优惠规则 */
        mcMchntFeeDiscountTransData.setBeforeFlag(tmMcMchntFeeDiscountInfo.getBeforeFlag());
        /* 达标后手续费优惠规则 */
        mcMchntFeeDiscountTransData.setAfterFlag(tmMcMchntFeeDiscountInfo.getAfterFlag());
        /* 优惠退出标志 */
        mcMchntFeeDiscountTransData.setTerminationFlag(tmMcMchntFeeDiscountInfo.getTerminationFlag());
        /* 统计周期 */
        mcMchntFeeDiscountTransData.setStatPeriod(tmMcMchntFeeDiscountInfo.getStatPeriod());
        /* 单个商户优惠交易笔数上限 */
        mcMchntFeeDiscountTransData.setQuantityLimit(tmMcMchntFeeDiscountInfo.getQuantityLimit());
        /* 单个商户优惠交易金额上限 */
        mcMchntFeeDiscountTransData.setAmountLimit(tmMcMchntFeeDiscountInfo.getAmountLimit());
        /* 单个商户手续费优惠额上限 */
        mcMchntFeeDiscountTransData.setFeeLimit(tmMcMchntFeeDiscountInfo.getFeeLimit());
        /* 新商户优惠额上限 */
        mcMchntFeeDiscountTransData.setNewMchntAmountLimit(tmMcMchntFeeDiscountInfo.getNewMchntAmountLimit());
        /* 营销活动预算 */
        mcMchntFeeDiscountTransData.setBudget(tmMcMchntFeeDiscountInfo.getBudget());
        /* 新增商户免费额度类型 */
        mcMchntFeeDiscountTransData.setNewmrctFreeLmtTyp(tmMcMchntFeeDiscountInfo.getNewmrctFreeLmtTyp());
    }

    /**
     * 使用主键取手续费减免活动商户单日统计表单条数据
     *
     * @param instId    法人机构号
     * @param mcNo      营销活动编号
     * @param ruleIndex 规则顺序号
     * @param mchntNo   商户编号
     * @param txnDate   交易日期
     * @return cc.rengu.igas.momp.common.entity.TMStatMfdMchntDay 手续费减免活动商户单日统计表
     * @throws Exception 异常信息
     * @author liujinan
     * @since 2020/9/25 15:23
     */
    private TMStatMfdMchntDay selectMchntFeeDiscountMchntDayStatisticsByPK(String instId, String mcNo, String ruleIndex, String mchntNo, String txnDate) throws Exception {

        TMStatMfdMchntDayMapper tmStatMfdMchntDayMapper = new TMStatMfdMchntDayMapperImpl();
        return tmStatMfdMchntDayMapper.selectMchntFeeDiscountMchntDayStatisticsByPK(instId, mcNo, ruleIndex, mchntNo, txnDate);
    }

    /**
     * 使用主键取手续费减免活动单日统计表单条数据
     *
     * @param instId    法人机构号
     * @param mcNo      营销活动编号
     * @param ruleIndex 规则顺序号
     * @param transDate 交易日期
     * @return cc.rengu.igas.momp.common.entity.TMStatMfdDay 手续费减免活动单日统计表
     * @throws Exception 异常信息
     * @author liujinan
     * @since 2020/9/25 15:23
     */
    private TMStatMfdDay selectMchntFeeDiscountDayStatisticsByPK(String instId, String mcNo, String ruleIndex, String transDate) throws Exception {

        TMStatMfdDayMapper tmStatMfdDayMapper = new TMStatMfdDayMapperImpl();
        return tmStatMfdDayMapper.selectMchntFeeDiscountDayStatisticsByPK(instId, mcNo, ruleIndex, transDate);
    }

    /**
     * 查询原交易订单明细信息
     *
     * @param instId        法人机构号
     * @param origTransDate 原交易日期
     * @param origTraceNo   原交易流水号
     * @return java.util.List<cc.rengu.igas.momp.common.entity.TMTxnOrderDet>
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/4/26 11:15
     */
    private List<TMTxnOrderDet> getOriginalTransactionOrderDetailInfo(String instId, String origTransDate, String origTraceNo) throws Exception {

        TMTxnOrderDetMapper tmTxnOrderDetMapper = new TMTxnOrderDetMapperImpl();
        return tmTxnOrderDetMapper.selectOriginalTransactionOrderDetailListInfo(instId, origTransDate, origTraceNo);
    }

    /**
     * 检查 上送 订单明细表 金额字段不能为负数
     *
     * @param comboMchntFeeDiscountRefundRequest
     * @author ls
     * @date 2020/10/21
     */
    private void checkOrderDetFieldHasNegativeNumber(ComboMchntFeeDiscountRefundRequest comboMchntFeeDiscountRefundRequest) {
        if (comboMchntFeeDiscountRefundRequest.getFeeReturnOrderList().size() > 0) {
            for (PaymentReturnOrderMchntFeeDiscountInfoBean paymentReturnOrderMchntFeeDiscountInfoBean : comboMchntFeeDiscountRefundRequest.getFeeReturnOrderList()) {
                /*退货订单金额	orderAmt*/
                if (!StringUtil.isNullorEmpty(paymentReturnOrderMchntFeeDiscountInfoBean.getOrderAmt()) && new BigDecimal(paymentReturnOrderMchntFeeDiscountInfoBean.getOrderAmt()).compareTo(zero) < 0) {
                    throw new BizException(RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespCode(), RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespDesc());
                }
                /*商户退货清算金额	mchntSettleAmt*/
                if (!StringUtil.isNullorEmpty(paymentReturnOrderMchntFeeDiscountInfoBean.getMchntSettleAmt()) && new BigDecimal(paymentReturnOrderMchntFeeDiscountInfoBean.getMchntSettleAmt()).compareTo(zero) < 0) {
                    throw new BizException(RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespCode(), RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespDesc());
                }
                /*退货商户应收手续费金额	mchntFeeReceivable*/
                if (!StringUtil.isNullorEmpty(paymentReturnOrderMchntFeeDiscountInfoBean.getMchntFeeReceivable()) && new BigDecimal(paymentReturnOrderMchntFeeDiscountInfoBean.getMchntFeeReceivable()).compareTo(zero) < 0) {
                    throw new BizException(RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespCode(), RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespDesc());
                }
                /*手续费优惠金额	mchntFeeDiscount*/
                if (!StringUtil.isNullorEmpty(paymentReturnOrderMchntFeeDiscountInfoBean.getMchntFeeDiscount()) && new BigDecimal(paymentReturnOrderMchntFeeDiscountInfoBean.getMchntFeeDiscount()).compareTo(zero) < 0) {
                    throw new BizException(RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespCode(), RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespDesc());
                }
                /*实收手续费金额	mchntFeeActual*/
                if (!StringUtil.isNullorEmpty(paymentReturnOrderMchntFeeDiscountInfoBean.getMchntFeeActual()) && new BigDecimal(paymentReturnOrderMchntFeeDiscountInfoBean.getMchntFeeActual()).compareTo(zero) < 0) {
                    throw new BizException(RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespCode(), RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespDesc());
                }
            }
        }
    }

    /**
     * 取商户手续费优惠类营销活动各维度统计数据
     *
     * @param mcMchntFeeDiscountTransData
     * @return int 返回码
     * @throws Exception 异常信息
     * @author liujinan
     * @since 2020/10/20 20:22
     */
    private void fetchNewMchntFeeDiscountMcQuotaData(McMchntFeeDiscountTransData mcMchntFeeDiscountTransData, TMStatMfdCriteria tmStatMfdCriteria) throws Exception {

        //规则维度批量处理状态
        int batchStatus_stat_mfd = CommonConstant.FLAG_NOT_SET;
        int batchStatus_stat_mfd_mchnt = CommonConstant.FLAG_NOT_SET;
        String instId = tmStatMfdCriteria.getInstId();
        String mcNo = tmStatMfdCriteria.getMcNo();
        String mchntNo = tmStatMfdCriteria.getMchntNo();
        String periodStartDate = tmStatMfdCriteria.getPeriodStartDate();
        String periodEndDate = tmStatMfdCriteria.getPeriodEndDate();
        String lastDate = DateUtil.getBaseDateOffsetDay(globalTxnDate, CommonConstant.MINUS_ONE);
        String lastSecondDate = DateUtil.getBaseDateOffsetDay(lastDate, CommonConstant.MINUS_ONE);
        String ruleIndex = CommonConstant.ZERO_COMMON_CONSTANT;
        String mfdCriteriaCreateTimeTmp = tmStatMfdCriteria.getCreateTime();
        String mfdCriteriaCreateTime = mfdCriteriaCreateTimeTmp.substring(0, 4) + mfdCriteriaCreateTimeTmp.substring(5, 7) + mfdCriteriaCreateTimeTmp.substring(8, 10);

        rglog.info("获取营销活动<{}>基本信息", mcNo);
        TMMcMchntFeeDiscountInfo tmMcMchntFeeDiscountInfo = getMchntFeeDiscountMcInfo(instId, mcNo);
        if (null == tmMcMchntFeeDiscountInfo) {
            rglog.error("机构<{}>的商户<{}>未获取到商户手续费优惠营销活动信息!", instId, mchntNo);
            throw new BizException(RespCodeEnum.GET_MONEY_OFF_MC_DETAIL_ERROR.getRespCode(), RespCodeEnum.GET_MONEY_OFF_MC_DETAIL_ERROR.getRespDesc());
        }
        convertMchntFeeDiscountMcInfo(tmMcMchntFeeDiscountInfo, mcMchntFeeDiscountTransData);

        String mcStartDate = tmMcMchntFeeDiscountInfo.getMcStartDate();
        String mcType = tmMcMchntFeeDiscountInfo.getMcType();

        /*------------------------------------------------查询营销活动商户维度汇总数据------------------------------------*/
        /* 查询商户手续费优惠营销活动商户统计表数据  查询具体规则维度的统计数值 新增商户的这个值应该为0*/
        TMStatMfdMchnt tmStatMfdMchnt = selectMchntFeeDiscountMchntStatisticsByPK(instId, mcNo, ruleIndex, mchntNo, periodStartDate, periodEndDate);
        if (null == tmStatMfdMchnt) {
            rglog.info("机构<{}>的营销活动<{}>的规则<{}>商户手续费优惠营销活动商户统计表数据查询失败!", globalInstId, mcNo, ruleIndex);

            /* 取到0条数据,说明该营销活动还未产生统计值,按所有统计值都是0进行处理 */
            tmStatMfdMchnt = new TMStatMfdMchnt();
            tmStatMfdMchnt.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchnt.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchnt.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchnt.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);

        }

        /* 查询商户手续费优惠营销活动商户单日统计表数据 具体规则编号的数据 新增商户的这个值应该为0*/
        TMStatMfdMchntDay tmStatMfdMchntDay = selectMchntFeeDiscountMchntDayStatisticsByPK(instId, mcNo, ruleIndex, mchntNo, globalTxnDate);
        if (null == tmStatMfdMchntDay) {
            rglog.error("机构<{}> 商户<{}> 商户手续费优惠营销活动<{}> 规则<{}> 商户手续费优惠营销活动商户单日统计表数据查询失败!", instId, mchntNo, mcNo, ruleIndex);
            tmStatMfdMchntDay = new TMStatMfdMchntDay();
            tmStatMfdMchntDay.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchntDay.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchntDay.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchntDay.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
        }
        String batchDate;
        //查询统计信息备份表批次信息 查询营销活动信息表的批量处理情况即可
        String statPrimaryKey = "FeeMchnt" + instId + "_" + mcNo;
        TMStatBak tmStatBak = selectTMStatBakByStatPrimaryKey(globalInstId, mcType, statPrimaryKey);
        //批次表为空，从来没执行过批量任务
        if (null == tmStatBak) {
            //从来没执行过批量任务，则从活动开始的第一天开始取数据
            batchDate = periodStartDate;
        } else {
            batchDate = DateUtil.getBaseDateOffsetDay(tmStatBak.getBatchDate(), 1);
        }
        //批量处理的日期小于昨天的日期，则需要取之前的数据
        while (DateUtil.compareDate(batchDate, lastDate) <= 0) {
            //获取的数据累加到活动统计中
            /* 查询商户手续费优惠营销活动商户单日统计表数据 具体规则编号的数据*/
            TMStatMfdMchntDay newtmStatMfdMchntDay = selectMchntFeeDiscountMchntDayStatisticsByPK(instId, mcNo, ruleIndex, mchntNo, batchDate);
            if (null == newtmStatMfdMchntDay) {
                rglog.error("机构<{}> 商户<{}> 商户手续费优惠营销活动<{}> 规则<{}> 商户手续费优惠营销活动商户单日统计表数据查询失败!", instId, mchntNo, mcNo, ruleIndex);
                newtmStatMfdMchntDay = new TMStatMfdMchntDay();
                newtmStatMfdMchntDay.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                newtmStatMfdMchntDay.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                newtmStatMfdMchntDay.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                newtmStatMfdMchntDay.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            }
            //将单日统计表的数据累加到周期数据上
            if (DateUtil.compareDate(batchDate, periodStartDate) < 0) {
                rglog.error("获取日期<{}>的单日统计不属于在本统计周期中，不需要累加到商户统计表!", batchDate);
            } else {
                rglog.error("获取日期<{}>的单日统计属于在本统计周期中，需要累加到商户统计表!", batchDate);
                copyMchntStatMfdData(tmStatMfdMchnt, newtmStatMfdMchntDay);
            }
            //将批次日期加一天继续判断
            batchDate = DateUtil.getBaseDateOffsetDay(batchDate, 1);
        }

        copyMchntFeeDiscountMchntStatData(tmStatMfdMchnt, mcMchntFeeDiscountTransData);
        copyMchntFeeDiscountMchntDayStatData(tmStatMfdMchntDay, mcMchntFeeDiscountTransData);

        /*------------------------------------------------查询营销活动维度汇总数据------------------------------------*/
        /* 查询商户手续费优惠营销活动统计表数据  规则为0的数据*/
        //查询统计信息备份表批次信息 查询营销活动信息表的批量处理情况即可
        statPrimaryKey = "Fee" + instId + "_" + mcNo;
        tmStatBak = selectTMStatBakByStatPrimaryKey(instId, McTypeEnum.MCHNT_FEE_DISCOUNT.getMcTypeCode(), statPrimaryKey);
        //批次表为空，从来没执行过批量任务
        if (null == tmStatBak) {
            //从来没执行过批量任务，则从活动开始的第一天开始取数据
            batchDate = mcStartDate;
        } else {
            batchDate = DateUtil.getBaseDateOffsetDay(tmStatBak.getBatchDate(), 1);
        }
        /* 查询商户手续费优惠营销活动统计表数据  规则为0的数据*/
        TMStatMfd tmStatMfd = selectMchntFeeDiscountStatisticsByPK(instId, mcNo, ruleIndex);
        if (null == tmStatMfd) {
            rglog.info("机构<{}>的营销活动<{}>的规则<{}>商户手续费优惠营销活动统计表数据查询失败!", globalInstId, mcNo, ruleIndex);

            /* 取到0条数据,说明该营销活动还未产生统计值,按所有统计值都是0进行处理 */
            tmStatMfd = new TMStatMfd();
            tmStatMfd.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfd.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfd.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfd.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);

        }

        //批量处理的日期小于昨天的日期，则需要取之前的数据
        while (DateUtil.compareDate(batchDate, lastDate) <= 0) {
            //循环获取单日统计表数据并累加
            /* 查询商户手续费优惠营销活动单日统计表数据 规则为0的数据*/
            TMStatMfdDay tmStatMfdDay1 = selectMchntFeeDiscountDayStatisticsByPK(instId, mcNo, ruleIndex, batchDate);
            if (null == tmStatMfdDay1) {
                rglog.error("机构<{}>的商户手续费优惠营销活动<{}>的规则<{}> 手续费减免活动单日统计表 数据查询失败!", instId, mcNo, ruleIndex);
                tmStatMfdDay1 = new TMStatMfdDay();
                tmStatMfdDay1.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                tmStatMfdDay1.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                tmStatMfdDay1.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                tmStatMfdDay1.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            }
            copyStatMfdData(tmStatMfd, tmStatMfdDay1);
            //将批次日期加一天继续判断
            batchDate = DateUtil.getBaseDateOffsetDay(batchDate, 1);
        }

        /* 查询商户手续费优惠营销活动单日统计表数据 规则为0的数据*/
        TMStatMfdDay tmStatMfdDay = selectMchntFeeDiscountDayStatisticsByPK(instId, mcNo, ruleIndex, globalTxnDate);
        if (null == tmStatMfdDay) {
            rglog.error("机构<{}>的商户手续费优惠营销活动<{}>的规则<{}> 手续费减免活动单日统计表 数据查询失败!", instId, mcNo, ruleIndex);
            tmStatMfdDay = new TMStatMfdDay();
            tmStatMfdDay.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdDay.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdDay.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdDay.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
        }

        //将累计优惠手续费金额赋值
        copyMchntFeeDiscountZeroStatData(tmStatMfd, tmStatMfdDay, mcMchntFeeDiscountTransData);
    }

    /**
     * 手续费减免活动统计数据赋值 规则为0的统计数据
     *
     * @param tmStatMfd    手续费减免活动统计表
     * @param tmStatMfdDay 手续费减免活动单日统计表
     * @author liujinan
     * @since 2020/10/20 11:22
     */
    private void copyMchntFeeDiscountZeroStatData(TMStatMfd tmStatMfd, TMStatMfdDay tmStatMfdDay, McMchntFeeDiscountTransData mcMchntFeeDiscountTransData) {
        /* 手续费减免活动统计数据-总预算消耗金额 */
        mcMchntFeeDiscountTransData.setMcTotalAmtAcc(new BigDecimal(tmStatMfd.getTotalAmtAcc()).add(new BigDecimal(tmStatMfdDay.getTotalAmtAcc())).toString());
    }

    /**
     * 判断新商户是否达到额度限制
     *
     * @author liujinan
     * @date 2020/10/20 17:27
     */
    private Boolean judgeNewMchntIsReachLimit(McMchntFeeDiscountTransData mcMchntFeeDiscountTransData, TMStatMfdCriteria tmStatMfdCriteria) throws Exception {

        String instId = tmStatMfdCriteria.getInstId();
        String mcNo = tmStatMfdCriteria.getMcNo();
        String mchntNo = tmStatMfdCriteria.getMchntNo();
        String newmrctFreeLmtTyp = mcMchntFeeDiscountTransData.getNewmrctFreeLmtTyp();

        //手续费减免活动商户统计 具体规则-累计优惠交易金额
        BigDecimal txnAmtAcc = new BigDecimal(mcMchntFeeDiscountTransData.getMchntTxnAmtAcc());
        //手续费减免活动商户单日统计数据 具体规则-累计优惠金额
        BigDecimal txnAmtAccDay = new BigDecimal(mcMchntFeeDiscountTransData.getMchntDayTxnAmtAcc());
        //手续费减免活动商户统计-累计优惠手续费金额
        BigDecimal mchntTotalAmtAcc = new BigDecimal(mcMchntFeeDiscountTransData.getMchntTotalAmtAcc()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
        //手续费减免活动商户单日统计数据 具体规则-累计优惠手续费金额
        BigDecimal mchntTotalAmtAccDay = new BigDecimal(mcMchntFeeDiscountTransData.getMchntDayTotalAmtAcc()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);

        if (null != tmStatMfdCriteria.getMrctDisUpLmtVal() && !"".equals(tmStatMfdCriteria.getMrctDisUpLmtVal())) {
            rglog.info("营销活动<{}> 商户<{}> 达标统计表 商户优惠上限值 字段有值，直接使用字段值<{}> 作为上限，无需通过计算规则重新计算!", mcNo, mchntNo, tmStatMfdCriteria.getMrctDisUpLmtVal());
            mcMchntFeeDiscountTransData.setNewMchntAmountLimit(tmStatMfdCriteria.getMrctDisUpLmtVal());
        } else {
        }

        /* 判断新商户优惠上限是否超限 */
        BigDecimal discountLimit = new BigDecimal(mcMchntFeeDiscountTransData.getNewMchntAmountLimit()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);

        //如果新商户上限为免交易金额，为空时默认为免交易金额
        if (null == newmrctFreeLmtTyp || CommonConstant.ZERO_COMMON_CONSTANT.equals(newmrctFreeLmtTyp)) {
            //周期统计累计优惠交易金额 + 单日统计累计优惠交易金额
            BigDecimal totalDiscount = txnAmtAcc.add(txnAmtAccDay).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
            rglog.info("新商户周期内优惠上限<{}>,目前已优惠金额<{}>", discountLimit, totalDiscount);

            if (totalDiscount.compareTo(discountLimit) >= CommonConstant.ZERO) {
                /*超过限额，不需要回退额度，*/
                rglog.info("法人机构<{}>的商户手续费优惠营销活动<{}> 新商户优惠交易额上限<{}> ，目前已优惠交易额<{}>，已超限额,不需要回退额度！", instId, mcNo, discountLimit, totalDiscount);
                return false;
            } else {
                /*未超过限额，需要回退额度，*/
                rglog.info("法人机构<{}>的商户手续费优惠营销活动<{}> 新商户优惠交易额上限<{}> ，目前已优惠交易额<{}>，未超限额,判断流程继续！", instId, mcNo, discountLimit, totalDiscount);
            }
        } else {
            //如果新商户上限为免手续费金额
            //周期统计累计优惠交易金额 + 单日统计累计优惠交易金额
            BigDecimal totalMchntFeeDiscount = mchntTotalAmtAcc.add(mchntTotalAmtAccDay).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
            rglog.info("新商户周期内优惠上限<{}>,目前已优惠手续费金额<{}>", discountLimit, totalMchntFeeDiscount);

            if (totalMchntFeeDiscount.compareTo(discountLimit) >= CommonConstant.ZERO) {
                /*超过限额，不需要回退额度，*/
                rglog.info("法人机构<{}>的商户手续费优惠营销活动<{}> 新商户优惠手续费上限<{}> ，目前已优惠手续费<{}>，已超限额,不需要回退额度！", instId, mcNo, discountLimit, totalMchntFeeDiscount);
                return false;
            } else {
                /*未超过限额，需要回退额度，*/
                rglog.info("法人机构<{}>的商户手续费优惠营销活动<{}> 新商户优惠手续费上限<{}> ，目前已优惠手续费<{}>，未超限额,判断流程继续！", instId, mcNo, discountLimit, totalMchntFeeDiscount);
            }
        }

        /* 判断活动预算资金是否达到上限 */
        //总预算
        BigDecimal budget = new BigDecimal(mcMchntFeeDiscountTransData.getBudget());
        if (budget.compareTo(BigDecimal.ZERO) > CommonConstant.ZERO) {
            //总预算累计消耗金额
            BigDecimal mcTotalAmtAcc = new BigDecimal(mcMchntFeeDiscountTransData.getMcTotalAmtAcc());
            if (mcTotalAmtAcc.compareTo(budget) >= CommonConstant.ZERO) {
                rglog.info("营销活动<{}>已累计优惠金额<{}> 活动总预算<{}> 达到额度值，不回退额度", mcMchntFeeDiscountTransData.getMcNo(), mcMchntFeeDiscountTransData.getMchntFeeDiscount(), mcMchntFeeDiscountTransData.getBudget());
                return false;
            }
        } else {
            rglog.info("默认预算资金无上限,不判断是否达到预算资金");
        }

        rglog.info("机构<{}>营销活动<{}> 规则<{}> 商户<{}> 各额度均未达到上限，需要回退额度", instId, mcNo, mcMchntFeeDiscountTransData.getRuleIndex(), mchntNo);
        return true;
    }

    /**
     * 使用主键取手续费减免活动统计表单条数据
     *
     * @param instId    法人机构编号
     * @param mcNo      营销活动编号
     * @param ruleIndex 规则顺序号
     * @return cc.rengu.igas.momp.common.entity.TMStatMfd 手续费减免活动统计表
     * @throws Exception 异常信息
     * @author liujinan
     * @since 2020/10/20 15:42
     */
    private TMStatMfd selectMchntFeeDiscountStatisticsByPK(String instId, String mcNo, String ruleIndex) throws Exception {

        TMStatMfdMapper tmStatMfdMapper = new TMStatMfdMapperImpl();
        return tmStatMfdMapper.selectMchntFeeDiscountStatisticsByPK(instId, mcNo, ruleIndex);
    }

    /**
     * 当前退货订单明细记录数据准备
     *
     * @return cc.rengu.igas.momp.common.entity.TMTxnOrderDet 订单明细表
     * @author liujinan
     * @since 2020/10/22 14:53
     */
    private void recordRefundTxnOrderDetail(PaymentReturnOrderMchntFeeDiscountInfoBean paymentReturnOrderMchntFeeDiscountInfoBean, TMTxnOrderDet oriTmTxnOrderDet) throws Exception {

        TMTxnOrderDet tmTxnOrderDet1 = new TMTxnOrderDet();

        /* 手续费优惠订单明细数据准备 */
        tmTxnOrderDet1.setInstId(globalInstId);
        tmTxnOrderDet1.setTxnDate(globalTxnDate);
        tmTxnOrderDet1.setFrontSeqNum(globalTraceNo);
        tmTxnOrderDet1.setOrderId(oriTmTxnOrderDet.getOrderId());
        tmTxnOrderDet1.setMchntNo(oriTmTxnOrderDet.getMchntNo());
        tmTxnOrderDet1.setUserId(oriTmTxnOrderDet.getUserId());
        tmTxnOrderDet1.setVerifyStatus(CommonConstant.VERIFY_STATUS_INIT);
        tmTxnOrderDet1.setBizStatus(BizStatusEnum.PROCESS_SUCCESS.getBizStatusCode());
        tmTxnOrderDet1.setMcType(oriTmTxnOrderDet.getMcType());
        BigDecimal originalAmt = new BigDecimal(paymentReturnOrderMchntFeeDiscountInfoBean.getMchntFeeReceivable()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
        tmTxnOrderDet1.setOriginalAmt(originalAmt.toString());
        tmTxnOrderDet1.setMcNo(oriTmTxnOrderDet.getMcNo());
        tmTxnOrderDet1.setRuleIndex(oriTmTxnOrderDet.getRuleIndex());
        tmTxnOrderDet1.setSubsidy(paymentReturnOrderMchntFeeDiscountInfoBean.getMchntFeeDiscount());
        tmTxnOrderDet1.setBankSubsidy(paymentReturnOrderMchntFeeDiscountInfoBean.getMchntFeeDiscount());
        tmTxnOrderDet1.setMchntSubsidy(CommonConstant.ZERO_AMOUNT);
        tmTxnOrderDet1.setRelativeData(oriTmTxnOrderDet.getRelativeData());
        tmTxnOrderDet1.setOrderRemark(oriTmTxnOrderDet.getOrderRemark());
        tmTxnOrderDet1.setOprId(CommonConstant.DEFAULT_OPR_ID);
        tmTxnOrderDet1.setCreateTime(globalTimeStamp);

        //关联信息
        String relativeData = oriTmTxnOrderDet.getRelativeData();
        JSONObject relativeDataJsonTrail = JSONObject.parseObject(relativeData);
        //原试算订单对应的 订单金额
        String origTrailOrderAmt = relativeDataJsonTrail.get("orderAmt").toString();
        //原试算订单对应的原订单 订单金额
        String origOrderAmt = relativeDataJsonTrail.get("origOrderAmt").toString();
        //原试算订单对应的原订单 实际优惠交易金额
        String origDisTxAmt;
        if (null == relativeDataJsonTrail.get("origDisTxAmt")) {
            origDisTxAmt = origOrderAmt;
        } else {
            origDisTxAmt = relativeDataJsonTrail.get("origDisTxAmt").toString();
        }
        BigDecimal origOrderAmtBigdecimal = new BigDecimal(origOrderAmt);
        BigDecimal OrigDisTxAmtBigdecimal = new BigDecimal(origDisTxAmt);
        //如果原订单金额和优惠交易金额相同，则 原交易不是商户最后一笔非全额优惠，则本笔优惠交易金额和本笔上送的优惠交易金额相同
        if (OrigDisTxAmtBigdecimal.compareTo(origOrderAmtBigdecimal) == 0) {
            //如果当前是最后部分退货的最后一笔退款，或者是全额退款，如果本笔交易有手续费优惠，则
            if (new BigDecimal(paymentReturnOrderMchntFeeDiscountInfoBean.getMchntFeeDiscount()).abs().compareTo(BigDecimal.ZERO) > 0) {
                tmTxnOrderDet1.setDisTxAmt(origTrailOrderAmt);
            } else {
                //如果没有手续费优惠，则本笔优惠交易金额为0
                tmTxnOrderDet1.setDisTxAmt(CommonConstant.ZERO_AMOUNT);
            }
        } else {
            //如果不相同，则原交易为此商户最后一笔非全金额手续费优惠,只有当最后一笔退款时登记优惠交易金额，其他时候为0
            if (isLastDeal) {
                tmTxnOrderDet1.setDisTxAmt(origDisTxAmt);
                //使用remark1标识，此订单虽然没有手续费优惠但是需要登记订单明细（有优惠交易金额）
                tmTxnOrderDet1.setRemark1(CommonConstant.ONE_COMMON_CONSTANT);
            } else {
                tmTxnOrderDet1.setDisTxAmt(CommonConstant.ZERO_AMOUNT);
            }
        }

        //如果手续费回退的交易有手续费优惠值，则登记订单明细表，如果没有则不登记
        if (new BigDecimal(paymentReturnOrderMchntFeeDiscountInfoBean.getMchntFeeDiscount()).abs().compareTo(BigDecimal.ZERO) > CommonConstant.ZERO
                || CommonConstant.ONE_COMMON_CONSTANT.equals(tmTxnOrderDet1.getRemark1())) {
            TMTxnOrderDetMapper tmTxnOrderDetMapper = new TMTxnOrderDetMapperImpl();
            /* 插入数据 */
            int returnCode = tmTxnOrderDetMapper.insertSingleRecordIntoTMTxnOrderDet(tmTxnOrderDet1);
            if (CommonConstant.PROCESS_SUCCESS != returnCode) {
                /* 更新失败 */
                rglog.error("登记法人机构<{}>的营销活动<{}>的商户<{}>的订单明细数据失败! RETURN_CODE=<{}>", tmTxnOrderDet1.getInstId(), tmTxnOrderDet1.getMcNo(), tmTxnOrderDet1.getMchntNo(), returnCode);
                throw new BizException(RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespCode(), RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespDesc());
            }

            globalTMTxnOrderDetList.add(tmTxnOrderDet1);
        }
    }

    /**
     * 使用主键查询手续费减免活动周期统计表单条数据
     *
     * @param instId
     * @param mcNo
     * @param ruleIndex
     * @param periodStartDate
     * @param periodEndDate
     * @return cc.rengu.igas.momp.common.entity.TMStatMfdPeriod
     * @throws Exception
     * @author liujinan
     * @date 2020/4/29
     */
    private TMStatMfdPeriod selectMchntFeeDiscountPeriodStatisticsByPK(String instId, String mcNo, String ruleIndex, String periodStartDate, String periodEndDate) throws Exception {

        TMStatMfdPeriodMapper tmStatMfdPeriodMapper = new TMStatMfdPeriodMapperImpl();
        return tmStatMfdPeriodMapper.selectMchntFeeDiscountPeriodStatisticsByPK(instId, mcNo, ruleIndex, periodStartDate, periodEndDate);
    }

    /**
     * 使用主键查询统计信息备份表最新一条数据
     *
     * @param instId
     * @param statType
     * @param statPrimaryKey
     * @return cc.rengu.igas.momp.common.entity.TMStatMfdPeriod
     * @throws Exception
     * @author liujinan
     * @date 2021/7/9
     */
    private TMStatBak selectTMStatBakByStatPrimaryKey(String instId, String statType, String statPrimaryKey) throws Exception {

        TMStatBakMapper tmStatBakMapper = new TMStatBakMapperImpl();
        return tmStatBakMapper.selectTMStatBakByStatPrimaryKey(instId, statType, statPrimaryKey);
    }

    /**
     * 手续费减免活动周期统计数据赋值
     *
     * @param tmStatMfdPeriod 手续费减免活动周期统计表
     * @param tmStatMfdDay    手续费减免活动单日统计表
     * @author liujinan
     * @since 2021/7/12 11:23
     */
    private void copyMchntFeeDiscountMchntStatData(TMStatMfdPeriod tmStatMfdPeriod, TMStatMfdDay tmStatMfdDay) {

        /* 手续费减免活动周期统计表-累计优惠笔数 */
        tmStatMfdPeriod.setTotalQtyAcc(new BigDecimal(tmStatMfdPeriod.getTotalQtyAcc()).add(new BigDecimal(tmStatMfdDay.getTotalQtyAcc())).toString());
        /* 手续费减免活动周期统计表-累计优惠金额 */
        tmStatMfdPeriod.setTotalAmtAcc(new BigDecimal(tmStatMfdPeriod.getTotalAmtAcc()).add(new BigDecimal(tmStatMfdDay.getTotalAmtAcc())).toString());
        /* 手续费减免活动周期统计表-累计交易笔数 */
        tmStatMfdPeriod.setTxnQtyAcc(new BigDecimal(tmStatMfdPeriod.getTxnQtyAcc()).add(new BigDecimal(tmStatMfdDay.getTxnQtyAcc())).toString());
        /* 手续费减免活动周期统计表-累计交易金额 */
        tmStatMfdPeriod.setTxnAmtAcc(new BigDecimal(tmStatMfdPeriod.getTxnAmtAcc()).add(new BigDecimal(tmStatMfdDay.getTxnAmtAcc())).toString());
    }

    /**
     * 手续费减免活动周期统计数据赋值 规则为0的统计数据
     *
     * @param tmStatMfdPeriod 手续费减免活动周期统计表
     * @param tmStatMfdDay    手续费减免活动周期统计表
     * @author liujinan
     * @since 2021/7/12 11:22
     */
    private void copyMchntFeeDiscountPeriodZeroStatData(TMStatMfdPeriod tmStatMfdPeriod, TMStatMfdDay tmStatMfdDay, McMchntFeeDiscountTransData mcMchntFeeDiscountTransData) {
        /* 手续费减免活动周期统计数据-周期内消耗金额+单日消耗金额*/
        mcMchntFeeDiscountTransData.setPeriodTotalAmtAcc(new BigDecimal(tmStatMfdPeriod.getTotalAmtAcc()).add(new BigDecimal(tmStatMfdDay.getTotalAmtAcc())).toString());
    }

    /**
     * 手续费减免活动商户统计数据赋值
     *
     * @param tmStatMfdMchnt    手续费减免活动商户统计表
     * @param tmStatMfdMchntDay 手续费减免活动商户单日统计表
     * @author Jinan Liu
     * @since 2020/6/5 11:23
     */
    private void copyMchntStatMfdData(TMStatMfdMchnt tmStatMfdMchnt, TMStatMfdMchntDay tmStatMfdMchntDay) {

        /* 营销活动单日累计-总预算累计消耗笔数 */
        tmStatMfdMchnt.setTotalQtyAcc(new BigDecimal(tmStatMfdMchnt.getTotalQtyAcc()).add(new BigDecimal(tmStatMfdMchntDay.getTotalQtyAcc())).toString());
        /* 营销活动单日累计-总预算累计消耗金额 */
        tmStatMfdMchnt.setTotalAmtAcc(new BigDecimal(tmStatMfdMchnt.getTotalAmtAcc()).add(new BigDecimal(tmStatMfdMchntDay.getTotalAmtAcc())).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).toString());
        /* 营销活动单日累计-总预算累计消耗笔数 */
        tmStatMfdMchnt.setTxnQtyAcc(new BigDecimal(tmStatMfdMchnt.getTxnQtyAcc()).add(new BigDecimal(tmStatMfdMchntDay.getTxnQtyAcc())).toString());
        /* 营销活动单日累计-总预算累计消耗金额 */
        tmStatMfdMchnt.setTxnAmtAcc(new BigDecimal(tmStatMfdMchnt.getTxnAmtAcc()).add(new BigDecimal(tmStatMfdMchntDay.getTxnAmtAcc())).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).toString());
    }

    /**
     * 手续费减免活动统计数据赋值
     *
     * @param tmStatMfd    手续费减免活动统计表
     * @param tmStatMfdDay 手续费减免活动单日统计表
     * @author Jinan Liu
     * @since 2020/6/5 11:23
     */
    private void copyStatMfdData(TMStatMfd tmStatMfd, TMStatMfdDay tmStatMfdDay) {

        /* 营销活动单日累计-总预算累计消耗笔数 */
        tmStatMfd.setTotalQtyAcc(new BigDecimal(tmStatMfd.getTotalQtyAcc()).add(new BigDecimal(tmStatMfdDay.getTotalQtyAcc())).toString());
        /* 营销活动单日累计-总预算累计消耗金额 */
        tmStatMfd.setTotalAmtAcc(new BigDecimal(tmStatMfd.getTotalAmtAcc()).add(new BigDecimal(tmStatMfdDay.getTotalAmtAcc())).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).toString());
        /* 营销活动单日累计-总预算累计消耗笔数 */
        tmStatMfd.setTxnQtyAcc(new BigDecimal(tmStatMfd.getTxnQtyAcc()).add(new BigDecimal(tmStatMfdDay.getTxnQtyAcc())).toString());
        /* 营销活动单日累计-总预算累计消耗金额 */
        tmStatMfd.setTxnAmtAcc(new BigDecimal(tmStatMfd.getTxnAmtAcc()).add(new BigDecimal(tmStatMfdDay.getTxnAmtAcc())).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).toString());
    }
}
